From 248642ffbf61c0a1e86bed9302811a57cefa46e1 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:37:41 +0100 Subject: [PATCH 01/19] feat: update and sync-up the recursive verifier fix: cleanup and restore security parameters chore: lower num of fri queries and small edits chore: cleanup chore: cleanup --- processor/src/operations/comb_ops.rs | 18 +- stdlib/asm/crypto/stark/constants.masm | 19 +- stdlib/asm/crypto/stark/deep_queries.masm | 207 +++++------------- stdlib/asm/crypto/stark/ood_frames.masm | 67 +++--- stdlib/asm/crypto/stark/public_inputs.masm | 2 +- stdlib/asm/crypto/stark/random_coin.masm | 43 ++-- stdlib/asm/crypto/stark/verifier.masm | 28 +-- stdlib/tests/crypto/stark/mod.rs | 3 +- .../stark/verifier_recursive/channel.rs | 136 +++++------- .../crypto/stark/verifier_recursive/mod.rs | 120 ++++++---- 10 files changed, 278 insertions(+), 365 deletions(-) diff --git a/processor/src/operations/comb_ops.rs b/processor/src/operations/comb_ops.rs index 03181d37ac..34f2b532b8 100644 --- a/processor/src/operations/comb_ops.rs +++ b/processor/src/operations/comb_ops.rs @@ -14,8 +14,8 @@ impl Process { /// \frac{T_i(x) - T_i(g \cdot z)}{x - g \cdot z} \right)} /// /// The instruction computes the numerators $\alpha_i \cdot (T_i(x) - T_i(z))$ and - /// $\alpha_i \cdot (T_i(x) - T_i(g \cdot z))$ and stores the values in two accumulators $p$ - /// and $r$, respectively. This instruction is specialized to main trace columns i.e. + /// $\alpha_i \cdot (T_i(x) - T_i(g \cdot z))$ and stores the values in two accumulators $r$ + /// and $p$, respectively. This instruction is specialized to main trace columns i.e. /// the values $T_i(x)$ are base field elements. /// /// The instruction is used in the context of STARK proof verification in order to compute @@ -44,9 +44,9 @@ impl Process { /// 1. Ti for i in 0..=7 stands for the the value of the i-th trace polynomial for the current /// query i.e. T_i(x). /// 2. (p0, p1) stands for an extension field element accumulating the values for the quotients - /// with common denominator (x - z). - /// 3. (r0, r1) stands for an extension field element accumulating the values for the quotients /// with common denominator (x - gz). + /// 3. (r0, r1) stands for an extension field element accumulating the values for the quotients + /// with common denominator (x - z). /// 4. x_addr is the memory address from which we are loading the Ti's using the MSTREAM /// instruction. /// 5. z_addr is the memory address to the i-th OOD evaluations at z and gz i.e. T_i(z):= @@ -72,7 +72,7 @@ impl Process { // --- compute the updated accumulator values --------------------------------------------- let v0 = self.stack.get(7); let tx = QuadFelt::new(v0, ZERO); - let [p_new, r_new] = [p + alpha * (tx - tz), r + alpha * (tx - tgz)]; + let [r_new, p_new] = [r + alpha * (tx - tz), p + alpha * (tx - tgz)]; // --- rotate the top 8 elements of the stack --------------------------------------------- self.stack.set(0, t0); @@ -258,8 +258,8 @@ mod tests { let a1 = a[1]; let alpha = QuadFelt::new(a0, a1); - let p_new = p + alpha * (tx - tz); - let r_new = r + alpha * (tx - tgz); + let p_new = p + alpha * (tx - tgz); + let r_new = r + alpha * (tx - tz); assert_eq!(p_new.to_base_elements()[1], stack_state[8]); assert_eq!(p_new.to_base_elements()[0], stack_state[9]); @@ -362,10 +362,10 @@ mod tests { expected.extend_from_slice(&[ZERO, Felt::from(18_u8), Felt::from(10_u8), Felt::from(2_u8)]); // updated accumulators expected.extend_from_slice(&[ - r.to_base_elements()[0], - r.to_base_elements()[1], p.to_base_elements()[0], p.to_base_elements()[1], + r.to_base_elements()[0], + r.to_base_elements()[1], ]); // the top 8 stack elements should equal tx since 8 calls to `rcomb_base` implies 8 circular // shifts of the top 8 elements i.e., the identity map on the top 8 element. diff --git a/stdlib/asm/crypto/stark/constants.masm b/stdlib/asm/crypto/stark/constants.masm index d062e2007d..fb44e35f95 100644 --- a/stdlib/asm/crypto/stark/constants.masm +++ b/stdlib/asm/crypto/stark/constants.masm @@ -17,15 +17,15 @@ const.TRACE_DOMAIN_GENERATOR_PTR=4294799999 const.PUBLIC_INPUTS_PTR=4294800000 # OOD Frames -# (72 + 9 + 8) * 2 * 2 Felt for current and next trace rows and 8 * 2 Felt for constraint composition -# polynomials. Total memory slots required: ((72 + 9 + 8) * 2 * 2 + 8 * 2) / 4 = 93 +# (70 + 7) * 2 * 2 Felt for current and next trace rows and 8 * 2 Felt for constraint composition +# polynomials. Total memory slots required: ((70 + 7) * 2 * 2 + 8 * 2) / 4 = 81 const.OOD_TRACE_PTR=4294900000 -const.OOD_CONSTRAINT_EVALS_PTR=4294900081 +const.OOD_CONSTRAINT_EVALS_PTR=4294900077 # Current trace row -# 72 Felt for main portion of trace, 9 * 2 Felt for auxiliary portion of trace and 8 * 2 Felt for +# 70 Felt for main portion of trace, 7 * 2 Felt for auxiliary portion of trace and 8 * 2 Felt for # constraint composition polynomials. Since we store these with the padding to make each of the -# three portions a multiple of 8, the number of slots required is (80 + 24 + 16) / 4 = 30 +# three portions a multiple of 8, the number of slots required is (72 + 16 + 16) / 4 = 26 const.CURRENT_TRACE_ROW_PTR=4294900100 # Random elements @@ -36,7 +36,7 @@ const.AUX_RAND_ELEM_PTR=4294900150 const.COMPOSITION_COEF_PTR=4294900200 # We need 2 Felt for each trace column and each of the 8 constraint composition columns. We thus need -# (72 + 9 + 8) * 2 Felt i.e. 44 memory slots. +# (70 + 7 + 8) * 2 Felt i.e. 43 memory slots. const.DEEP_RAND_CC_PTR=4294903000 # FRI @@ -80,7 +80,6 @@ const.GRINDING_FACTOR_PTR=4294903308 # RPO capacity initialization words const.ZERO_WORD_PTR=4294903309 -const.ZERO_ZERO_ZERO_ONE_PTR=4294903310 # State of RPO-based random coin const.C_PTR=4294903311 @@ -106,7 +105,7 @@ const.TMP8=4294903322 # | TRACE_DOMAIN_GENERATOR_PTR | 4294799999 | # | PUBLIC_INPUTS_PTR | 4294800000 | # | OOD_TRACE_PTR | 4294900000 | -# | OOD_CONSTRAINT_EVALS_PTR | 4294900081 | +# | OOD_CONSTRAINT_EVALS_PTR | 4294900077 | # | CURRENT_TRACE_ROW_PTR | 4294900100 | # | AUX_RAND_ELEM_PTR | 4294900150 | # | COMPOSITION_COEF_PTR | 4294900200 | @@ -238,10 +237,6 @@ export.zero_word push.ZERO_WORD_PTR end -export.zero_zero_zero_one_word - push.ZERO_ZERO_ZERO_ONE_PTR -end - #! Returns the pointer to the capacity word of the random coin. #! #! Note: The random coin is implemented using a hash function, this returns the diff --git a/stdlib/asm/crypto/stark/deep_queries.masm b/stdlib/asm/crypto/stark/deep_queries.masm index ce8ef49e30..0ce9e0e962 100644 --- a/stdlib/asm/crypto/stark/deep_queries.masm +++ b/stdlib/asm/crypto/stark/deep_queries.masm @@ -1,127 +1,5 @@ use.std::crypto::stark::constants - -#! Computes a single step of the random linear combination defining the DEEP composition polynomial -#! that is the input to the FRI protocol. More precisely, the sum in question is: -#! $$ -#! \sum_{i=0}^k{\alpha_i \cdot \left(\frac{T_i(x) - T_i(z)}{x - z} + -#! \frac{T_i(x) - T_i(z \cdot g)}{x - z \cdot g} \right)} -#! $$ -#! -#! and the following instruction computes the denominators $\alpha_i \cdot (T_i(x) - T_i(z))$ and -#! $\alpha_i \cdot (T_i(x) - T_i(z \cdot g))$ and stores the values in two accumulators $r$ and $p$, -#! respectively. This instruction is specialized to main trace columns i.e. the values $T_i(x)$ are -#! base field elements. -#! -#! The stack transition of the instruction can be visualized as follows: -#! -#! +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+---+ -#! | T7 | T6 | T5 | T4 | T3 | T2 | T1 | T0 | p1 | p0 | r1 | r0 |x_addr|z_addr|a_addr| - | -#! +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+---+ -#! -#! || -#! \/ -#! -#! +------+------+------+------+------+------+------+------+------+------+------+------+------+--------+--------+---+ -#! | T0 | T7 | T6 | T5 | T4 | T3 | T2 | T1 | p1' | p0' | r1' | r0' |x_addr|z_addr+1|a_addr+1| - | -#! +------+------+------+------+------+------+------+------+------+------+------+------+------+--------+--------+---+ -#! -#! -#! Here: -#! 1- Ti for i in 0..=7 stands for the the value of the i-th trace polynomial for the current query i.e. T_i(x). -#! 2- (p0, p1) stands for an extension field element accumulating the values for the quotients with common denominator (x - gz). -#! 3- (r0, r1) stands for an extension field element accumulating the values for the quotients with common denominator (x - z). -#! 4- x_addr is the memory address from which we are loading the Ti's using the MSTREAM instruction. -#! 5- z_addr is the memory address to the i-th OOD evaluation frame at z and gz i.e. T_i(z):= (T_i(z)0, T_i(z)1) -#! and T_i(gz):= (T_i(gz)0, T_i(gz)1) -#! 6- a_addr is the memory address of the i-th random element used in batching the trace polynomial quotients. -#! The random elements a := (a0, a1) are stored in memory as [0, 0, a0, a1]. -#! -#! Input: [T7, T6, T5, T4, T3, T2, T1, T0, p1, p0, r1, r0, x_addr, z_addr, a_addr, 0] -#! Output: [T0, T7, T6, T5, T4, T3, T2, T1, p1', p0', r1', r0', x_addr, z_addr+1, a_addr+1, 0] -export.combine_main - - # 1) Shift trace columns values left - movup.7 - #=> [T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr, a_addr, 0] - - # 2) Get a_addr and update it. This is done here before the element becomes inaccessible. - - # Update a_addr - dup.14 add.1 swap.15 - #=> [a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr, a_addr', 0] - - # 3) Load i-th OOD frame portion. This assumes that the OOD frame has been serialized with `current` and `next` rows interleaved. - # This also updates the z_addr pointer. - dup.14 add.1 swap.15 - padw movup.4 mem_loadw - #=> [Tgz1, Tgz0, Tz1, Tz0, a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # 4) Compute the numerators - - # a) Compute T_i - T_i(z). This equals, in the case of T0, (-Tz1, T0 - Tz0) - dup.5 - movup.4 - #=> [Tz0, T0, Tgz1, Tgz0, Tz1, a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - sub - #=> [T0 - Tz0, Tgz1, Tgz0, Tz1, a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - swap.3 neg swap.2 - #=> [Tgz0, Tgz1, -Tz1, T0 - Tz0, a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # b) Compute T_i - T_i(gz). This equals, in the case of T0, (-Tgz1, T0 - Tgz0) - dup.5 swap sub - #=> [T0 - Tgz0, Tgz1, -Tz1, T0 - Tz0, a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - swap - neg - #=> [-Tgz1, T0 - Tgz0, -Tz1, T0 - Tz0, a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - #=> [Δg1, Δg0, Δ1, Δ0, a_addr, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - # where Δg1 := -Tgz1, Δg0 := T0 - Tgz0, Δ1 := -Tz1 and Δ0 := T0 - Tz0 - - # 5) Multiply by randomness - - # a) Load randomness from memory - padw - movup.8 mem_loadw drop drop - #=> [a1, a0, Δg1, Δg0, Δ1, Δ0, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # b) Multiply (Δ0, Δ1) - dup.1 dup.1 - movup.7 movup.7 - #=> [Δ1, Δ0, a1, a0, a1, a0, Δg1, Δg0, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - ext2mul - #=> [prod1, prod0, a1, a0, Δg1, Δg0, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - # where (prod0, prod1) := (Δ0, Δ1) * (a0, a1) - - movdn.5 movdn.5 - #=> [a1, a0, Δg1, Δg0, prod1, prod0, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # c) Multiply (Δg0, Δg1) - ext2mul - #=> [prodg1, prodg0, prod1, prod0, T0, T7, T6, T5, T4, T3, T2, T1, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - # where (prodg0, prodg1) := (Δg0, Δg1) * (a0, a1) - - # 6) Accumulate into (p0, p1) and (r0, r1) - movupw.3 - - # a) Accumulate into (r0, r1) - movup.7 movup.7 - #=> [prod1, prod0, p1, p0, r1, r0, prodg1, prodg0, T0, T7, T6, T5, T4, T3, T2, T1, x_addr, z_addr', a_addr', 0] - movup.5 movup.5 ext2add - #=> [r1', r0', p1, p0, prodg1, prodg0, T0, T7, T6, T5, T4, T3, T2, T1, x_addr, z_addr', a_addr', 0] - - # b) Accumulate into (p0, p1) - movdn.5 movdn.5 ext2add - #=> [p1', p0', r1', r0', T0, T7, T6, T5, T4, T3, T2, T1, x_addr, z_addr', a_addr', 0] - - # c) Prepare for next iteration. - movdnw.2 - #=> [T0, T7, T6, T5, T4, T3, T2, T1, p1', p0', r1', r0', x_addr, z_addr', a_addr', 0] -end - #! Computes a single step of the random linear combination defining the DEEP composition polynomial #! that is the input to the FRI protocol. More precisely, the sum in question is: #! $$ @@ -252,7 +130,7 @@ end #! Input: [query_ptr, ...] #! Output: [index, query_ptr, ...] #! -#! Cycles: 198 +#! Cycles: 219 proc.load_query_row # Main trace portion of the query @@ -280,14 +158,31 @@ proc.load_query_row swapw #=>[R, ptr, y, y, y, depth, index, query_ptr, ...] exec.constants::zero_word mem_loadw + add.6 + swap.3 padw padw #=> [Y, Y, 0, 0, 0, 1, ptr, y, y, y] - repeat.9 + repeat.8 adv_pipe hperm end #=> [Y, L, Y, ptr, y, y, y, depth, index, query_ptr, ...] + ## Store the last full word of main segment columns + adv_loadw + dup.12 mem_storew + swapw + dropw + adv_push.1 + adv_push.1 + push.0 + push.0 + ## Store the last 2 main segment columns + dup.12 add.1 mem_storew + + ## Final hperm + hperm + ## Load the leaf value we got using mtree_get exec.constants::tmp3 mem_loadw @@ -301,6 +196,9 @@ proc.load_query_row assert_eq #=> [Y, ptr, y, y, y, depth, index, query_ptr, ...] + ## increment ptr to account for the last two words we loaded from the advice tape + swapw add.2 swapw + # Aux trace part @@ -314,25 +212,19 @@ proc.load_query_row #=> [L, R, ptr, y, y, y, depth, index, query_ptr, ...] ## adv_pipe aux trace portion - push.1.0.0.0 + push.6.0.0.0 swapw.2 adv_pipe hperm - adv_pipe hperm + adv_loadw + dup.12 mem_storew + swapw dropw adv_push.1 adv_push.1 - push.1 - push.0 - - ## Store the 9-th auxiliary column - dup.12 mem_storew + push.0.0 - ## Since combine_aux follows a mem_stream we need to store (i.e. pad with) the all zero word in - ## order to avoid over-stepping into the constraint polynomial columns. - swapw - exec.constants::zero_word mem_loadw - dup.12 add.1 - mem_storew + ## Store the last aux segment column + dup.12 add.1 mem_storew ## Final hperm hperm @@ -439,7 +331,7 @@ end #! The procedure then outputs a stack in the same configuration but with the pointers and accumulators #! updated to [Y`, Y`, Acc`, P`, ...] where: #! -#! 1. P` := [CURRENT_TRACE_ROW_PTR+18, OOD_TRACE_PTR+72, DEEP_RAND_CC_PTR+72, 0]. +#! 1. P` := [CURRENT_TRACE_ROW_PTR+18, OOD_TRACE_PTR+70, DEEP_RAND_CC_PTR+70, 0]. #! 2. [Y`, Y`] is a "garbage" double-word used to later mem_stream auxiliary portion referenced now #! by CURRENT_TRACE_ROW_PTR`. #! 3. Acc` is the accumulator holding the updated numerator values i.e. with terms involving main @@ -450,12 +342,17 @@ end #! #! Cycles: 81 proc.combine_main_trace_columns - repeat.9 + repeat.8 mem_stream repeat.8 - exec.combine_main + rcomb_base end end + + mem_stream + repeat.6 + rcomb_base + end end #! Computes the random linear combination involving the aux trace columns and accumulates @@ -470,7 +367,7 @@ end #! The procedure then outputs a stack in the same configuration but with the pointers and accumulators #! updated to [Y`, Y`, Acc`, P`, ...] where: #! -#! 1. P` := [CURRENT_TRACE_ROW_PTR+6, OOD_TRACE_PTR+9, DEEP_RAND_CC_PTR+9, 0]. +#! 1. P` := [CURRENT_TRACE_ROW_PTR+4, OOD_TRACE_PTR+7, DEEP_RAND_CC_PTR+7, 0]. #! 2. [Y`, Y`] is a "garbage" double-word used to later mem_stream constraint composition polynomial #! trace portion referenced now by CURRENT_TRACE_ROW_PTR`. #! 3. Acc` is the accumulator holding the updated numerator values i.e. with terms involving main @@ -479,19 +376,19 @@ end #! Input: [Y, Y, Acc, P, ...] #! Output: [Y`, Y`, Acc`, P`, ...] #! -#! Cycles: 12 +#! Cycles: 9 proc.combine_aux_trace_columns - # Compute the random linear combination of the first 8 auxiliary trace columns - repeat.2 - mem_stream - repeat.4 - exec.combine_aux - end + # Compute the random linear combination of the first 4 auxiliary trace columns + mem_stream + repeat.4 + exec.combine_aux end - # and the 9th aux column + # Compute the random linear combination of the last 3 auxiliary trace columns mem_stream - exec.combine_aux + repeat.3 + exec.combine_aux + end end #! Computes the random linear combination involving the constraint composition polynomial trace @@ -512,7 +409,7 @@ end #! Input: [Y, Y, Acc, P, ...] #! Output: [Acc`, ...] #! -#! Cycles: 33 +#! Cycles: 25 proc.combine_constraint_poly_columns # Save Acc swapw.2 @@ -570,7 +467,7 @@ end #! #! Input: [query_ptr, ...] #! Output: [...] -#! Cycles: 6 + num_queries * 463 +#! Cycles: 6 + num_queries * 473 export.compute_deep_composition_polynomial_queries exec.constants::fri_com_ptr dup.1 @@ -583,7 +480,7 @@ export.compute_deep_composition_polynomial_queries # Load the (main, aux, constraint)-traces rows associated with the current query and get # the index of the query. # - # Cycles: 200 + # Cycles: 219 exec.load_query_row #=>[index, query_ptr, query_end_ptr, ...] @@ -629,9 +526,9 @@ export.compute_deep_composition_polynomial_queries ## d) Compute the random linear combination ## - ## Cycles: 81 + 12 + 33 = 126 + ## Cycles: 81 + 9 + 25 = 115 exec.combine_main_trace_columns - exec.combine_aux_trace_columns + exec.combine_aux_trace_columns exec.combine_constraint_poly_columns #=> [Acc, Z, x, index, query_ptr, query_end_ptr, ...] diff --git a/stdlib/asm/crypto/stark/ood_frames.masm b/stdlib/asm/crypto/stark/ood_frames.masm index bb3fabc1bc..b162d71b77 100644 --- a/stdlib/asm/crypto/stark/ood_frames.masm +++ b/stdlib/asm/crypto/stark/ood_frames.masm @@ -7,20 +7,20 @@ use.std::crypto::hashes::rpo #! #! Input: [...] #! Output: [OOD_FRAME_HASH, ...] -#! Cycles: 106 +#! Cycles: 100 export.load_evaluation_frame - # We have 72 main trace columns and 9 aux trace columns for a total of 162 base field elements + # We have 70 main trace columns and 7 aux trace columns for a total of 154 base field elements # per row. Since we have two rows, i.e. current and next, the total number of field elements # making up the OOD evaluation frame is: - # 324 = 40 * 8 + 4 + # 324 = 38 * 8 + 4 # The elements are stored from the stack as (a1_1, a1_0, a0_1, a0_0) where a0 is from the # current row and a1 from the next row. exec.constants::ood_trace_ptr - push.1.0.0.0 + push.4.0.0.0 padw padw - repeat.40 + repeat.38 adv_pipe hperm end @@ -29,7 +29,7 @@ export.load_evaluation_frame adv_loadw dup.12 mem_storew swapw - exec.constants::zero_zero_zero_one_word mem_loadw + exec.constants::zero_word mem_loadw hperm dropw @@ -113,40 +113,49 @@ end #! #! Input: [...] #! Output: [res1, res0, ...] -#! Cycles: 118 +#! Cycles: 152 export.compute_Hz - # TODO: remove this + # Load the pointer to the OOD constraint polynomials evaluations exec.constants::ood_constraint_evals_ptr - add.4 - repeat.3 - padw - end + # => [ptr, ...] # Compute `H(z)` ## Load `value_i`'s - dup.12 - sub.4 - mem_loadw - swapw.2 + # Load value_0 + padw dup.4 mem_loadw + # => [0, 0, v0_1, v0_0, ptr, ...] + + # Load value_1 + push.0.0 dup.6 add.1 mem_loadw + # => [0, 0, v1_1, v1_0, v0_1, v0_0, ptr, ...] - dup.12 - sub.3 - mem_loadw - swapw + # Load value_2 + push.0.0 dup.8 add.2 mem_loadw + # => [0, 0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] - dup.12 - sub.2 - mem_loadw + # Load value_3 + push.0.0 dup.10 add.3 mem_loadw + # => [0, 0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] - movup.12 - sub.1 - padw - movup.4 - mem_loadw + # Load value_4 + push.0.0 dup.12 add.4 mem_loadw + # => [0, 0, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_5 + push.0.0 movup.14 movdn.4 dup.4 add.5 mem_loadw + # => [0, 0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_6 + push.0.0 dup.6 add.6 mem_loadw + # => [0, 0, v6_1, v6_0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_7 + push.0.0 movup.8 add.7 mem_loadw + # => [0, 0, v7_1, v7_0, v6_1, v6_0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] ## Load z^N where N is the length of the execution trace - padw + push.0.0 exec.constants::z_ptr mem_loadw movup.2 drop movup.2 drop diff --git a/stdlib/asm/crypto/stark/public_inputs.masm b/stdlib/asm/crypto/stark/public_inputs.masm index 4ea8426b3c..a837288d3e 100644 --- a/stdlib/asm/crypto/stark/public_inputs.masm +++ b/stdlib/asm/crypto/stark/public_inputs.masm @@ -28,7 +28,7 @@ export.load end adv_loadw swapw - exec.constants::zero_zero_zero_one_word mem_loadw + exec.constants::zero_word mem_loadw hperm dropw diff --git a/stdlib/asm/crypto/stark/random_coin.masm b/stdlib/asm/crypto/stark/random_coin.masm index 07f431cb22..b37044e871 100644 --- a/stdlib/asm/crypto/stark/random_coin.masm +++ b/stdlib/asm/crypto/stark/random_coin.masm @@ -95,11 +95,6 @@ export.init_seed exec.constants::c_ptr mem_storew exec.constants::r1_ptr mem_storew exec.constants::r2_ptr mem_storew - - drop - push.1 - swap.3 - exec.constants::zero_zero_zero_one_word mem_storew dropw #=> [log(trace_length), num_queries, log(blowup), grinding] @@ -164,36 +159,32 @@ export.init_seed exec.constants::trace_domain_generator_ptr mem_store #=> [0, trace_length, num_queries, blowup, grinding] - # clean satck + # clean stack drop #=> [trace_length, num_queries, blowup, grinding] # Construct the proof context ##trace layout info - push.1208027408 - + push.1174472464 ##field modulus bytes (2 field elements) push.1 push.4294967295 - ## field extension and FRI parameters push.132103 - # Hash proof context # Cycles: 15 swapw - push.1.0.0.0 - #=> [0, 0, 0, 1, B, A, ..] - swapw.2 - swapw - #=> [B, A, 0, 0, 0, 1, ..] + movdn.6 + push.4.0.0.0 + movdnw.2 + # => [B, A, 0, 0, 0, 4, ..] hperm dropw dropw - #=> [C] -end + # => [C] + end #! Reseed the random coin with `DATA` #! @@ -422,7 +413,7 @@ end #! #! Input: [aux_rand_elem_ptr, ...] #! Output: [...] -#! Cycles: 150 +#! Cycles: 159 export.generate_aux_randomness push.16 swap @@ -431,14 +422,14 @@ export.generate_aux_randomness end #! Draw constraint composition random coefficients and save them into memory in the region from -#! `compos_coef_ptr` `compos_coef_ptr + 118 - 1` as `(r1_1, r1_0, r0_1, r0_0)` +#! `compos_coef_ptr` `compos_coef_ptr + 112 - 1` as `(r1_1, r1_0, r0_1, r0_0)` #! #! Input: [compos_coef_ptr, ...] #! Output: [...] -#! Cycles: 1309 +#! Cycles: 1305 export.generate_constraint_composition_coefficients - push.236 + push.224 swap exec.generate_random_coefficients #=> [...] @@ -447,16 +438,16 @@ end #! Draw deep composition polynomial random coefficients and save them into memory in the region from #! `deep_rand_coef_ptr` to `deep_rand_coef_ptr + 89 - 1` as `(0, 0, r0_1, r0_0)` #! The number of coefficients is equal to: -#! 1. (72 + 9) * 2 Felt for the main and auxiliary traces. +#! 1. (70 + 7) * 2 Felt for the main and auxiliary traces. #! 2. 8 * 2 Felt for constraint polynomial. -#! Total: 89 tuples of type (Felt, Felt) +#! Total: 85 tuples of type (Felt, Felt) #! #! Input: [deep_rand_coef_ptr, ...] #! Output: [...] -#! Cycles: 1693 +#! Cycles: 1624 export.generate_deep_composition_random_coefficients - - push.92 + # note that 88 is the next number after 85 divisible by 4 + push.88 swap exec.generate_random_coefficients_pad #=> [...] diff --git a/stdlib/asm/crypto/stark/verifier.masm b/stdlib/asm/crypto/stark/verifier.masm index 3b4fc05a03..edcc4adeca 100644 --- a/stdlib/asm/crypto/stark/verifier.masm +++ b/stdlib/asm/crypto/stark/verifier.masm @@ -12,25 +12,25 @@ use.std::crypto::stark::constants #! The following simplifying assumptions are currently made: #! - The blowup is set to 8. #! - The maximal allowed degree of the remainder polynomial is 7. -#! - Only the input and output stacks, assumed of fixed size equal to 16, are handled in regards -#! to public inputs. +#! - The public inputs are composed of the input and output stacks, of fixed size equal to 16. #! - There are two trace segments, main and auxiliary. It is assumed that the main trace segment -#! is 73 columns wide while the auxiliary trace segment is 9 columns wide. +#! is 70 columns wide while the auxiliary trace segment is 7 columns wide. #! - The OOD evaluation frame is composed of two interleaved rows, current and next, each composed -#! of 73 elements representing the main trace portion and 9 elements for the auxiliary trace one. +#! of 70 elements representing the main trace portion and 7 elements for the auxiliary trace one. #! - To boost soundness, the protocol is run on a quadratic extension field and this means that #! the OOD evaluation frame is composed of elements in a quadratic extension field i.e. tuples. -#! Similarly, elements of the auxiliary trace are quadratic extension field elements. +#! Similarly, elements of the auxiliary trace are quadratic extension field elements. The random +#! values for computing random linear combinations are also in this extension field. #! - The following procedure makes use of global memory address beyond 3 * 2^30 and these are #! defined in `constants.masm`. #! -#! Input: [log(trace_length), num_queries, log(blowup), grinding] +#! Input: [log(trace_length), num_queries, log(blowup), grinding, ...] #! Output: [] #! Cycles: #! 1- Remainder codeword size 32: -#! 5000 + num_queries * (40 + num_fri_layers * 76 + 26 + 463) + 83 * num_fri_layers + 10 * log(trace_length) + 1633 +#! 4975 + num_queries * (40 + num_fri_layers * 76 + 26 + 473) + 83 * num_fri_layers + 10 * log(trace_length) + 1633 #! 2- Remainder codeword size 64: -#! 5000 + num_queries * (40 + num_fri_layers * 76 + 26 + 463) + 83 * num_fri_layers + 10 * log(trace_length) + 3109 +#! 4975 + num_queries * (40 + num_fri_layers * 76 + 26 + 473) + 83 * num_fri_layers + 10 * log(trace_length) + 3109 export.verify #============================================================================================== @@ -67,7 +67,7 @@ export.verify # Draw random ExtFelt for the auxiliary trace # - # Cycles: 150 + # Cycles: 160 exec.constants::aux_rand_elem_ptr exec.random_coin::generate_aux_randomness #=> [...] @@ -85,7 +85,7 @@ export.verify # III) Draw constraint composition coefficients #============================================================================================== - # Cycles: 1309 + # Cycles: 1306 exec.constants::composition_coef_ptr exec.random_coin::generate_constraint_composition_coefficients #=> [...] @@ -110,7 +110,7 @@ export.verify # of H over the LDE domain. #============================================================================================== - # Cycles: 106 + # Cycles: 104 exec.ood_frames::load_evaluation_frame #=> [OOD_FRAME_HASH, ...] @@ -126,7 +126,7 @@ export.verify # Compute `H(z)` # - # Cycles: 118 + # Cycles: 152 exec.ood_frames::compute_Hz #=> [res1, res0, ...] @@ -147,7 +147,7 @@ export.verify # DEEP composition polynomial. #============================================ - # Cycles: 1693 + # Cycles: 1625 exec.constants::deep_rand_coef_ptr exec.random_coin::generate_deep_composition_random_coefficients @@ -221,7 +221,7 @@ export.verify # Compute deep compostion polynomial queries # - # Cycles: 14 + num_queries * 463 + # Cycles: 14 + num_queries * 473 #=> [query_ptr, ...] exec.deep_queries::compute_deep_composition_polynomial_queries #=> [query_ptr, ...] diff --git a/stdlib/tests/crypto/stark/mod.rs b/stdlib/tests/crypto/stark/mod.rs index b81a6f4b2b..0db959448b 100644 --- a/stdlib/tests/crypto/stark/mod.rs +++ b/stdlib/tests/crypto/stark/mod.rs @@ -10,7 +10,6 @@ use verifier_recursive::{generate_advice_inputs, VerifierData}; // Note: Changes to MidenVM may cause this test to fail when some of the assumptions documented // in `stdlib/asm/crypto/stark/verifier.masm` are violated. #[test] -#[ignore] fn stark_verifier_e2f4() { // An example MASM program to be verified inside Miden VM. // Note that output stack-overflow is not yet supported because of the way we handle public @@ -53,7 +52,7 @@ pub fn generate_recursive_verifier_data( let mut host = DefaultHost::new(advice_provider); let options = - ProvingOptions::new(43, 8, 12, FieldExtension::Quadratic, 4, 7, HashFunction::Rpo256); + ProvingOptions::new(27, 8, 12, FieldExtension::Quadratic, 4, 7, HashFunction::Rpo256); let (stack_outputs, proof) = prove(&program, stack_inputs.clone(), &mut host, options).unwrap(); diff --git a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs index 0ae32bcdfd..418fbacdbc 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs @@ -1,14 +1,11 @@ -// VERIFIER CHANNEL -// ================================================================================================ - use alloc::vec::Vec; use miden_air::ProcessorAir; use test_utils::{ - crypto::{BatchMerkleProof, MerklePath, PartialMerkleTree, Rpo256, RpoDigest}, + crypto::{BatchMerkleProof, PartialMerkleTree, Rpo256, RpoDigest}, group_slice_elements, math::{FieldElement, QuadExtension, StarkField}, - Felt, MerkleTreeVC, VerifierError, EMPTY_WORD, + Felt, MerkleTreeVC, VerifierError, }; use winter_air::{ proof::{Proof, Queries, Table, TraceOodFrame}, @@ -170,24 +167,27 @@ impl VerifierChannel { positions: &[usize], ) -> Result<(AdvMap, Vec), VerifierError> { let queries = self.trace_queries.take().expect("already read"); - let mut trees = Vec::new(); - - let proofs: Vec<_> = queries.query_proofs.into_iter().collect(); - let main_queries = queries.main_states.clone(); - let aux_queries = queries.aux_states.clone(); + let proofs = queries.query_proofs; + let main_queries = queries.main_states; + let aux_queries = queries.aux_states; let main_queries_vec: Vec> = main_queries.rows().map(|a| a.to_owned()).collect(); + let aux_queries_vec: Vec> = aux_queries .as_ref() .unwrap() .rows() .map(|a| QuadExt::slice_as_base_elements(a).to_vec()) .collect(); + let (main_trace_pmt, mut main_trace_adv_map) = unbatch_to_partial_mt(positions.to_vec(), main_queries_vec, proofs[0].clone()); let (aux_trace_pmt, mut aux_trace_adv_map) = unbatch_to_partial_mt(positions.to_vec(), aux_queries_vec, proofs[1].clone()); + + let mut trees = Vec::new(); trees.push(main_trace_pmt); trees.push(aux_trace_pmt); + main_trace_adv_map.append(&mut aux_trace_adv_map); Ok((main_trace_adv_map, trees)) } @@ -202,85 +202,58 @@ impl VerifierChannel { let queries = self.constraint_queries.take().expect("already read"); let proof = queries.query_proofs; - let queries_: Vec> = queries + let queries = queries .evaluations .rows() - .map(|a| a.iter().flat_map(|x| QuadExt::to_base_elements(*x).to_owned()).collect()) + .map(|a| QuadExt::slice_as_base_elements(a).into()) .collect(); let (constraint_pmt, constraint_adv_map) = - unbatch_to_partial_mt(positions.to_vec(), queries_, proof); + unbatch_to_partial_mt(positions.to_vec(), queries, proof); Ok((constraint_adv_map, constraint_pmt)) } - // Get the FRI layer challenges alpha - pub fn fri_layer_commitments(&self) -> Option> { - self.fri_roots.clone() - } - - // Get remainder codeword - pub fn fri_remainder(&self) -> Vec { - self.fri_remainder.clone().unwrap() - } - // - pub fn layer_proofs(&self) -> Vec> { + /// Returns the FRI layers Merkle batch proofs. + pub fn fri_layer_proofs(&self) -> Vec> { self.fri_layer_proofs.clone() } - pub fn unbatch( + /// Returns the unbatched Merkle proofs as well as a global key-value map for all the FRI layer + /// proofs. + pub fn unbatch_fri_layer_proofs( &mut self, positions_: &[usize], domain_size: usize, layer_commitments: Vec, ) -> (Vec, Vec<(RpoDigest, Vec)>) { - let queries = self.fri_layer_queries.clone(); + let all_layers_queries = self.fri_layer_queries.clone(); let mut current_domain_size = domain_size; let mut positions = positions_.to_vec(); - let depth = layer_commitments.len() - 1; + let number_of_folds = layer_commitments.len() - 1; - let mut adv_key_map = Vec::new(); - let mut partial_trees = Vec::new(); - let mut layer_proofs = self.layer_proofs(); - for query in queries.iter().take(depth) { + let mut global_adv_key_map = Vec::new(); + let mut global_partial_merkle_trees = Vec::new(); + let mut layer_proofs = self.fri_layer_proofs(); + for current_layer_queries in all_layers_queries.iter().take(number_of_folds) { let mut folded_positions = fold_positions(&positions, current_domain_size, N); let layer_proof = layer_proofs.remove(0); - let x = group_slice_elements::(query); - let leaves: Vec = x.iter().map(|row| Rpo256::hash_elements(row)).collect(); - let unbatched_proof = layer_proof.into_openings(&leaves, &folded_positions).unwrap(); - assert_eq!(x.len(), unbatched_proof.len()); - - let nodes: Vec<[Felt; 4]> = - leaves.iter().map(|leaf| [leaf[0], leaf[1], leaf[2], leaf[3]]).collect(); - - let paths: Vec = - unbatched_proof.into_iter().map(|list| list.1.into()).collect(); + let queries: Vec<_> = group_slice_elements::(current_layer_queries) + .iter() + .map(|query| QuadExt::slice_as_base_elements(query).to_vec()) + .collect(); - let iter_pos = folded_positions.iter_mut().map(|a| *a as u64); - let nodes_tmp = nodes.clone(); - let iter_nodes = nodes_tmp.iter(); - let iter_paths = paths.into_iter(); - let mut tmp_vec = Vec::new(); - for (p, (node, path)) in iter_pos.zip(iter_nodes.zip(iter_paths)) { - tmp_vec.push((p, RpoDigest::from(*node), path)); - } + let (current_partial_merkle_tree, mut cur_adv_key_map) = + unbatch_to_partial_mt(folded_positions.clone(), queries, layer_proof); - let new_pmt = - PartialMerkleTree::with_paths(tmp_vec).expect("should not fail from paths"); - partial_trees.push(new_pmt); - - nodes.into_iter().zip(x.iter()).for_each(|(a, b)| { - let mut value = QuadExt::slice_as_base_elements(b).to_owned(); - value.extend(EMPTY_WORD); - - adv_key_map.push((a.to_owned().into(), value)); - }); + global_partial_merkle_trees.push(current_partial_merkle_tree); + global_adv_key_map.append(&mut cur_adv_key_map); core::mem::swap(&mut positions, &mut folded_positions); current_domain_size /= N; } - (partial_trees, adv_key_map) + (global_partial_merkle_trees, global_adv_key_map) } } @@ -425,36 +398,41 @@ impl ConstraintQueries { // HELPER FUNCTIONS // ================================================================================================ +/// Takes a set of positions, query values of a trace at these positions and a Merkle batch proof +/// against a committment to this trace, and outputs a partial Merkle tree with individual Merkle +/// paths for each position as well as a key-value map mapping the digests of the query values +/// (i.e. Merkle tree leaves) to their corresponding query values. pub fn unbatch_to_partial_mt( - mut positions: Vec, + positions: Vec, queries: Vec>, proof: BatchMerkleProof, ) -> (PartialMerkleTree, Vec<(RpoDigest, Vec)>) { + // hash the query values in order to get the leaf let leaves: Vec = queries.iter().map(|row| Rpo256::hash_elements(row)).collect(); - let unbatched_proof = proof.into_openings(&leaves, &positions).unwrap(); - let mut adv_key_map = Vec::new(); - let nodes: Vec<[Felt; 4]> = - queries.iter().map(|node| [node[0], node[1], node[2], node[3]]).collect(); - - let paths: Vec = unbatched_proof.into_iter().map(|list| list.1.into()).collect(); - - let iter_pos = positions.iter_mut().map(|a| *a as u64); - let nodes_tmp = nodes.clone(); - let iter_nodes = nodes_tmp.iter(); - let iter_paths = paths.into_iter(); - let mut tmp_vec = vec![]; - for (p, (node, path)) in iter_pos.zip(iter_nodes.zip(iter_paths)) { - tmp_vec.push((p, RpoDigest::from(*node), path)); + // use the computed leaves with the indices in order to unbatch the Merkle proof batch proof + let unbatched_proof = proof + .into_openings(&leaves, &positions) + .expect("failed to unbatch the batched Merkle proof"); + + // construct the partial Merkle tree data + let mut paths_with_leaves = vec![]; + for (position, merkle_proof) in positions.iter().zip(unbatched_proof.iter()) { + paths_with_leaves.push(( + *position as u64, + merkle_proof.0.to_owned(), + merkle_proof.1.to_owned().into(), + )) } - nodes.into_iter().zip(queries.iter()).for_each(|(a, b)| { - let data = b.to_owned(); - adv_key_map.push((a.to_owned().into(), data)); + // construct the advice key map linking leaves to query values + let mut adv_key_map = Vec::new(); + leaves.into_iter().zip(queries.iter()).for_each(|(leaf, query_data)| { + adv_key_map.push((leaf, query_data.to_owned())); }); ( - PartialMerkleTree::with_paths(tmp_vec).expect("should not fail from paths"), + PartialMerkleTree::with_paths(paths_with_leaves).expect("should not fail from paths"), adv_key_map, ) } diff --git a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs index 85a38d0675..899621a3be 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs @@ -8,6 +8,7 @@ use test_utils::{ Felt, VerifierError, }; use winter_air::{proof::Proof, Air}; +use winter_fri::VerifierChannel as FriVerifierChannel; mod channel; use channel::VerifierChannel; @@ -27,21 +28,28 @@ pub fn generate_advice_inputs( proof: Proof, pub_inputs: ::PublicInputs, ) -> Result { - //// build a seed for the public coin; the initial seed is the hash of public inputs and proof - //// context, but as the protocol progresses, the coin will be reseeded with the info received - //// from the prover - let mut public_coin_seed = proof.context.to_elements(); - let trace_len: Felt = public_coin_seed[7]; + // we need to provide the following instance specific data through the operand stack + let proof_context = proof.context.to_elements(); + let trace_len: Felt = proof_context[1]; + let num_queries = proof_context[7]; + let blowup = proof_context[6]; + let grinding_factor = proof_context[5]; let initial_stack = vec![ - public_coin_seed[4].as_int(), - (public_coin_seed[5].as_int() as usize).ilog2() as u64, - public_coin_seed[6].as_int(), + grinding_factor.as_int(), + (blowup.as_int() as usize).ilog2() as u64, + num_queries.as_int(), (trace_len.as_int() as usize).ilog2() as u64, ]; + // build a seed for the public coin; the initial seed is the hash of public inputs and proof + // context, but as the protocol progresses, the coin will be reseeded with the info received + // from the prover let mut tape = vec![]; + let mut public_coin_seed = proof.context.to_elements(); public_coin_seed.append(&mut pub_inputs.to_elements()); + // add the public inputs, which is nothing but the input and output stacks to the VM, to the + // advice tape let pub_inputs_int: Vec = pub_inputs.to_elements().iter().map(|a| a.as_int()).collect(); tape.extend_from_slice(&pub_inputs_int[..]); @@ -51,14 +59,16 @@ pub fn generate_advice_inputs( let mut public_coin: RpoRandomCoin = RpoRandomCoin::new(seed_digest.into()); let mut channel = VerifierChannel::new(&air, proof)?; - // 1 ----- trace commitment ------------------------------------------------------------------- + // 1 ----- main segment trace ----------------------------------------------------------------- let trace_commitments = channel.read_trace_commitments(); - // reseed the coin with the commitment to the main trace segment + // reseed the coin with the commitment to the main segment trace public_coin.reseed(trace_commitments[0]); tape.extend_from_slice(&digest_to_int_vec(trace_commitments)); - // process auxiliary trace segments, to build a set of random elements for each segment + // 2 ----- auxiliary segment trace ------------------------------------------------------------ + + // generate the auxiliary random elements let mut aux_trace_rand_elements = vec![]; for commitment in trace_commitments.iter().skip(1) { let rand_elements: Vec = air @@ -67,85 +77,119 @@ pub fn generate_advice_inputs( aux_trace_rand_elements.push(rand_elements); public_coin.reseed(*commitment); } - // build random coefficients for the composition polynomial + + // 3 ----- constraint composition trace ------------------------------------------------------- + + // build random coefficients for the composition polynomial. we don't need them but we have to + // generate them in order to update the random coin let _constraint_coeffs: winter_air::ConstraintCompositionCoefficients = air .get_constraint_composition_coefficients(&mut public_coin) .map_err(|_| VerifierError::RandomCoinError)?; - - // 2 ----- constraint commitment -------------------------------------------------------------- let constraint_commitment = channel.read_constraint_commitment(); tape.extend_from_slice(&digest_to_int_vec(&[constraint_commitment])); public_coin.reseed(constraint_commitment); - // 3 ----- OOD frames -------------------------------------------------------------- + // 4 ----- OOD frames -------------------------------------------------------------- + + // generate the the OOD point + let _z: QuadExt = public_coin.draw().unwrap(); + + // read the main and auxiliary segments' OOD frames and add them to advice tape let ood_trace_frame = channel.read_ood_trace_frame(); let _ood_main_trace_frame = ood_trace_frame.main_frame(); let _ood_aux_trace_frame = ood_trace_frame.aux_frame(); - // TODO: fix - tape.extend_from_slice(&to_int_vec(ood_trace_frame.current_row())); - public_coin.reseed(Rpo256::hash_elements(ood_trace_frame.current_row())); + let mut main_and_aux_frame_states = Vec::new(); + for col in 0.._ood_main_trace_frame.current().len() { + main_and_aux_frame_states.push(_ood_main_trace_frame.current()[col]); + main_and_aux_frame_states.push(_ood_main_trace_frame.next()[col]); + } + for col in 0.._ood_aux_trace_frame.as_ref().unwrap().current().len() { + main_and_aux_frame_states.push(_ood_aux_trace_frame.as_ref().unwrap().current()[col]); + main_and_aux_frame_states.push(_ood_aux_trace_frame.as_ref().unwrap().next()[col]); + } + tape.extend_from_slice(&to_int_vec(&main_and_aux_frame_states)); + public_coin.reseed(Rpo256::hash_elements(&main_and_aux_frame_states)); - // read evaluations of composition polynomial columns + // read OOD evaluations of composition polynomial columns let ood_constraint_evaluations = channel.read_ood_constraint_evaluations(); tape.extend_from_slice(&to_int_vec(&ood_constraint_evaluations)); public_coin.reseed(Rpo256::hash_elements(&ood_constraint_evaluations)); - // 4 ----- FRI -------------------------------------------------------------------- - let fri_commitments_digests = channel.fri_layer_commitments().unwrap(); - let poly = channel.fri_remainder(); + // 5 ----- FRI ------------------------------------------------------------------------------- + + // read the FRI layer committments as well as remainder polynomial + let fri_commitments_digests = channel.read_fri_layer_commitments(); + let poly = channel.read_remainder().unwrap(); + + // Reed-Solomon encode the remainder polynomial as this is needed for the probabilistic NTT let twiddles = fft::get_twiddles(poly.len()); let fri_remainder = fft::evaluate_poly_with_offset(&poly, &twiddles, Felt::GENERATOR, BLOWUP_FACTOR); + // add the above to the advice tape let fri_commitments: Vec = digest_to_int_vec(&fri_commitments_digests); tape.extend_from_slice(&fri_commitments); tape.extend_from_slice(&to_int_vec(&poly)); tape.extend_from_slice(&to_int_vec(&fri_remainder)); + // reseed with FRI layer commitments let _deep_coefficients = air .get_deep_composition_coefficients::(&mut public_coin) .map_err(|_| VerifierError::RandomCoinError)?; - // Reseed with FRI layer commitments let layer_commitments = fri_commitments_digests.clone(); for commitment in layer_commitments.iter() { public_coin.reseed(*commitment); let _alpha: QuadExt = public_coin.draw().expect("failed to draw random indices"); } - // 5 ----- trace and constraint queries ------------------------------------------------------- + // 6 ----- trace and constraint queries ------------------------------------------------------- // read proof-of-work nonce sent by the prover and draw pseudo-random query positions for - // the LDE domain from the public coin. - // This is needed in order to construct Partial Merkle Trees + // the LDE domain from the public coin let pow_nonce = channel.read_pow_nonce(); - let query_positions = public_coin + let mut query_positions = public_coin .draw_integers(air.options().num_queries(), air.lde_domain_size(), pow_nonce) .map_err(|_| VerifierError::RandomCoinError)?; + tape.extend_from_slice(&[pow_nonce]); + query_positions.sort(); + query_positions.dedup(); - // read advice maps and Merkle paths related to trace and constraint composition polynomial - // evaluations - let (mut advice_map, mut partial_trees_traces) = + // read advice maps and Merkle paths of the queries to main/aux and constraint composition traces + let (mut main_aux_adv_map, mut partial_trees_traces) = channel.read_queried_trace_states(&query_positions)?; - let (mut adv_map_constraint, partial_tree_constraint) = + let (mut constraint_adv_map, partial_tree_constraint) = channel.read_constraint_evaluations(&query_positions)?; - let domain_size = (air.trace_poly_degree() + 1) * BLOWUP_FACTOR; - let mut ress = channel.unbatch::<4, 3>(&query_positions, domain_size, fri_commitments_digests); + let (mut partial_trees_fri, mut fri_adv_map) = channel.unbatch_fri_layer_proofs::<4>( + &query_positions, + air.lde_domain_size(), + fri_commitments_digests, + ); + // consolidate advice maps - advice_map.append(&mut adv_map_constraint); - advice_map.append(&mut ress.1); - let mut partial_trees_fri = ress.0; + main_aux_adv_map.append(&mut constraint_adv_map); + main_aux_adv_map.append(&mut fri_adv_map); + + // build the full MerkleStore partial_trees_fri.append(&mut partial_trees_traces); partial_trees_fri.push(partial_tree_constraint); let mut store = MerkleStore::new(); for partial_tree in &partial_trees_fri { store.extend(partial_tree.inner_nodes()); } - Ok(VerifierData { initial_stack, tape, store, advice_map }) + + Ok(VerifierData { + initial_stack, + tape, + store, + advice_map: main_aux_adv_map, + }) } -// Helpers +// HELPER FUNCTIONS +// ================================================================================================ + pub fn digest_to_int_vec(digest: &[RpoDigest]) -> Vec { digest .iter() From 37460fd305832c4d7335e600ffef93bdd5ae6363 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Fri, 15 Nov 2024 09:14:36 +0100 Subject: [PATCH 02/19] chore: update changelog and fix clippy --- CHANGELOG.md | 1 + stdlib/tests/crypto/stark/verifier_recursive/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf5c12887d..ab9c09580c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - Debug instructions can be enabled in the cli `run` command using `--debug` flag (#1502). - Added support for procedure annotation (attribute) syntax to Miden Assembly (#1510). - Make `miden-prover::prove()` method conditionally asynchronous (#1563). +- Update and sync the recursive verifier (#1575). #### Changes diff --git a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs index 899621a3be..0299dc4d13 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs @@ -155,7 +155,8 @@ pub fn generate_advice_inputs( query_positions.sort(); query_positions.dedup(); - // read advice maps and Merkle paths of the queries to main/aux and constraint composition traces + // read advice maps and Merkle paths of the queries to main/aux and constraint composition + // traces let (mut main_aux_adv_map, mut partial_trees_traces) = channel.read_queried_trace_states(&query_positions)?; let (mut constraint_adv_map, partial_tree_constraint) = From 9e83deb557e4da9c4a6613419c48c70dbc13562b Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Fri, 15 Nov 2024 09:27:53 +0100 Subject: [PATCH 03/19] fix: clippy --- stdlib/tests/crypto/stark/verifier_recursive/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs index 418fbacdbc..51d97cdffc 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs @@ -184,7 +184,7 @@ impl VerifierChannel { let (aux_trace_pmt, mut aux_trace_adv_map) = unbatch_to_partial_mt(positions.to_vec(), aux_queries_vec, proofs[1].clone()); - let mut trees = Vec::new(); + let mut trees = vec![]; trees.push(main_trace_pmt); trees.push(aux_trace_pmt); From 95ec91c42bb78ba8026ee8845f1ddf13ef5cf473 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Fri, 15 Nov 2024 09:31:58 +0100 Subject: [PATCH 04/19] fix: clippy --- stdlib/tests/crypto/stark/verifier_recursive/channel.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs index 51d97cdffc..8a92142064 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs @@ -184,8 +184,7 @@ impl VerifierChannel { let (aux_trace_pmt, mut aux_trace_adv_map) = unbatch_to_partial_mt(positions.to_vec(), aux_queries_vec, proofs[1].clone()); - let mut trees = vec![]; - trees.push(main_trace_pmt); + let mut trees = vec![main_trace_pmt]; trees.push(aux_trace_pmt); main_trace_adv_map.append(&mut aux_trace_adv_map); From 79da3c0fd6e6773e2326e7a33e729803e7a8c665 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:40:11 +0100 Subject: [PATCH 05/19] chore: address feedback --- processor/src/operations/comb_ops.rs | 10 ++--- stdlib/asm/crypto/stark/constants.masm | 10 +++++ stdlib/asm/crypto/stark/random_coin.masm | 13 +++++-- stdlib/tests/crypto/stark/mod.rs | 8 +++- .../crypto/stark/verifier_recursive/mod.rs | 37 ++++++++----------- 5 files changed, 46 insertions(+), 32 deletions(-) diff --git a/processor/src/operations/comb_ops.rs b/processor/src/operations/comb_ops.rs index 34f2b532b8..498026f038 100644 --- a/processor/src/operations/comb_ops.rs +++ b/processor/src/operations/comb_ops.rs @@ -72,7 +72,7 @@ impl Process { // --- compute the updated accumulator values --------------------------------------------- let v0 = self.stack.get(7); let tx = QuadFelt::new(v0, ZERO); - let [r_new, p_new] = [r + alpha * (tx - tz), p + alpha * (tx - tgz)]; + let [p_new, r_new] = [p + alpha * (tx - tgz), r + alpha * (tx - tz)]; // --- rotate the top 8 elements of the stack --------------------------------------------- self.stack.set(0, t0); @@ -337,8 +337,8 @@ mod tests { let tz: Vec = tz_tgz.iter().step_by(2).map(|e| e.to_owned()).collect(); let tgz: Vec = tz_tgz.iter().skip(1).step_by(2).map(|e| e.to_owned()).collect(); for i in 0..8 { - p += a[i] * (QuadFelt::from(tx[i]) - tz[i]); - r += a[i] * (QuadFelt::from(tx[i]) - tgz[i]); + p += a[i] * (QuadFelt::from(tx[i]) - tgz[i]); + r += a[i] * (QuadFelt::from(tx[i]) - tz[i]); } // prepare the advice stack with the generated data @@ -362,10 +362,10 @@ mod tests { expected.extend_from_slice(&[ZERO, Felt::from(18_u8), Felt::from(10_u8), Felt::from(2_u8)]); // updated accumulators expected.extend_from_slice(&[ - p.to_base_elements()[0], - p.to_base_elements()[1], r.to_base_elements()[0], r.to_base_elements()[1], + p.to_base_elements()[0], + p.to_base_elements()[1], ]); // the top 8 stack elements should equal tx since 8 calls to `rcomb_base` implies 8 circular // shifts of the top 8 elements i.e., the identity map on the top 8 element. diff --git a/stdlib/asm/crypto/stark/constants.masm b/stdlib/asm/crypto/stark/constants.masm index fb44e35f95..cf8784c9d7 100644 --- a/stdlib/asm/crypto/stark/constants.masm +++ b/stdlib/asm/crypto/stark/constants.masm @@ -5,6 +5,8 @@ const.ROOT_UNITY=7277203076849721926 const.DOMAIN_OFFSET=7 const.DOMAIN_OFFSET_INV=2635249152773512046 +const.NUM_CONSTRAINT_COMPOSITION_COEF_MULTIPLIED_BY_TWO_ROUNDED_UP_TO_FOUR=224 +const.NUM_DEEP_COMPOSITION_COEF_MULTIPLIED_BY_TWO_ROUNDED_UP_TO_FOUR=88 # MEMORY POINTERS @@ -159,6 +161,14 @@ export.domain_offset_inv push.DOMAIN_OFFSET_INV end +export.num_constraint_composition_coef_multiplied_by_two_and_rounded_up_to_4 + push.NUM_CONSTRAINT_COMPOSITION_COEF_MULTIPLIED_BY_TWO_ROUNDED_UP_TO_FOUR +end + +export.num_deep_composition_coef_multiplied_by_two_and_rounded_up_to_4 + push.NUM_DEEP_COMPOSITION_COEF_MULTIPLIED_BY_TWO_ROUNDED_UP_TO_FOUR +end + export.public_inputs_ptr push.PUBLIC_INPUTS_PTR end diff --git a/stdlib/asm/crypto/stark/random_coin.masm b/stdlib/asm/crypto/stark/random_coin.masm index b37044e871..3bf36227db 100644 --- a/stdlib/asm/crypto/stark/random_coin.masm +++ b/stdlib/asm/crypto/stark/random_coin.masm @@ -165,9 +165,14 @@ export.init_seed # Construct the proof context - ##trace layout info + ## trace layout info, which is the concatenation as u8-s of: + ## 1. main segment width + ## 2. num auxiliary segments, which always 1 + ## 3. auxiliary segment width + ## 4. number of auxiliary random values + ## 5. trace length push.1174472464 - ##field modulus bytes (2 field elements) + ## field modulus bytes (2 field elements) push.1 push.4294967295 ## field extension and FRI parameters @@ -429,7 +434,7 @@ end #! Cycles: 1305 export.generate_constraint_composition_coefficients - push.224 + exec.constants::num_constraint_composition_coef_multiplied_by_two_and_rounded_up_to_4 swap exec.generate_random_coefficients #=> [...] @@ -447,7 +452,7 @@ end #! Cycles: 1624 export.generate_deep_composition_random_coefficients # note that 88 is the next number after 85 divisible by 4 - push.88 + exec.constants::num_deep_composition_coef_multiplied_by_two_and_rounded_up_to_4 swap exec.generate_random_coefficients_pad #=> [...] diff --git a/stdlib/tests/crypto/stark/mod.rs b/stdlib/tests/crypto/stark/mod.rs index 0db959448b..c72d725158 100644 --- a/stdlib/tests/crypto/stark/mod.rs +++ b/stdlib/tests/crypto/stark/mod.rs @@ -24,8 +24,12 @@ fn stark_verifier_e2f4() { stack_inputs[15] = 0; stack_inputs[14] = 1; - let VerifierData { initial_stack, tape, store, advice_map } = - generate_recursive_verifier_data(example_source, stack_inputs).unwrap(); + let VerifierData { + initial_stack, + advice_stack: tape, + store, + advice_map, + } = generate_recursive_verifier_data(example_source, stack_inputs).unwrap(); // Verify inside Miden VM let source = " diff --git a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs index 0299dc4d13..2d59f5119e 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs @@ -19,7 +19,7 @@ pub type QuadExt = QuadExtension; #[derive(Debug, Clone, Eq, PartialEq)] pub struct VerifierData { pub initial_stack: Vec, - pub tape: Vec, + pub advice_stack: Vec, pub store: MerkleStore, pub advice_map: Vec<(RpoDigest, Vec)>, } @@ -29,29 +29,24 @@ pub fn generate_advice_inputs( pub_inputs: ::PublicInputs, ) -> Result { // we need to provide the following instance specific data through the operand stack - let proof_context = proof.context.to_elements(); - let trace_len: Felt = proof_context[1]; - let num_queries = proof_context[7]; - let blowup = proof_context[6]; - let grinding_factor = proof_context[5]; let initial_stack = vec![ - grinding_factor.as_int(), - (blowup.as_int() as usize).ilog2() as u64, - num_queries.as_int(), - (trace_len.as_int() as usize).ilog2() as u64, + proof.context.options().grinding_factor() as u64, + proof.context.options().blowup_factor().ilog2() as u64, + proof.context.options().num_queries() as u64, + proof.context.trace_info().length().ilog2() as u64, ]; // build a seed for the public coin; the initial seed is the hash of public inputs and proof // context, but as the protocol progresses, the coin will be reseeded with the info received // from the prover - let mut tape = vec![]; + let mut advice_stack = vec![]; let mut public_coin_seed = proof.context.to_elements(); public_coin_seed.append(&mut pub_inputs.to_elements()); // add the public inputs, which is nothing but the input and output stacks to the VM, to the // advice tape let pub_inputs_int: Vec = pub_inputs.to_elements().iter().map(|a| a.as_int()).collect(); - tape.extend_from_slice(&pub_inputs_int[..]); + advice_stack.extend_from_slice(&pub_inputs_int[..]); // create AIR instance for the computation specified in the proof let air = ProcessorAir::new(proof.trace_info().to_owned(), pub_inputs, proof.options().clone()); @@ -64,7 +59,7 @@ pub fn generate_advice_inputs( // reseed the coin with the commitment to the main segment trace public_coin.reseed(trace_commitments[0]); - tape.extend_from_slice(&digest_to_int_vec(trace_commitments)); + advice_stack.extend_from_slice(&digest_to_int_vec(trace_commitments)); // 2 ----- auxiliary segment trace ------------------------------------------------------------ @@ -86,7 +81,7 @@ pub fn generate_advice_inputs( .get_constraint_composition_coefficients(&mut public_coin) .map_err(|_| VerifierError::RandomCoinError)?; let constraint_commitment = channel.read_constraint_commitment(); - tape.extend_from_slice(&digest_to_int_vec(&[constraint_commitment])); + advice_stack.extend_from_slice(&digest_to_int_vec(&[constraint_commitment])); public_coin.reseed(constraint_commitment); // 4 ----- OOD frames -------------------------------------------------------------- @@ -108,12 +103,12 @@ pub fn generate_advice_inputs( main_and_aux_frame_states.push(_ood_aux_trace_frame.as_ref().unwrap().current()[col]); main_and_aux_frame_states.push(_ood_aux_trace_frame.as_ref().unwrap().next()[col]); } - tape.extend_from_slice(&to_int_vec(&main_and_aux_frame_states)); + advice_stack.extend_from_slice(&to_int_vec(&main_and_aux_frame_states)); public_coin.reseed(Rpo256::hash_elements(&main_and_aux_frame_states)); // read OOD evaluations of composition polynomial columns let ood_constraint_evaluations = channel.read_ood_constraint_evaluations(); - tape.extend_from_slice(&to_int_vec(&ood_constraint_evaluations)); + advice_stack.extend_from_slice(&to_int_vec(&ood_constraint_evaluations)); public_coin.reseed(Rpo256::hash_elements(&ood_constraint_evaluations)); // 5 ----- FRI ------------------------------------------------------------------------------- @@ -129,9 +124,9 @@ pub fn generate_advice_inputs( // add the above to the advice tape let fri_commitments: Vec = digest_to_int_vec(&fri_commitments_digests); - tape.extend_from_slice(&fri_commitments); - tape.extend_from_slice(&to_int_vec(&poly)); - tape.extend_from_slice(&to_int_vec(&fri_remainder)); + advice_stack.extend_from_slice(&fri_commitments); + advice_stack.extend_from_slice(&to_int_vec(&poly)); + advice_stack.extend_from_slice(&to_int_vec(&fri_remainder)); // reseed with FRI layer commitments let _deep_coefficients = air @@ -151,7 +146,7 @@ pub fn generate_advice_inputs( let mut query_positions = public_coin .draw_integers(air.options().num_queries(), air.lde_domain_size(), pow_nonce) .map_err(|_| VerifierError::RandomCoinError)?; - tape.extend_from_slice(&[pow_nonce]); + advice_stack.extend_from_slice(&[pow_nonce]); query_positions.sort(); query_positions.dedup(); @@ -182,7 +177,7 @@ pub fn generate_advice_inputs( Ok(VerifierData { initial_stack, - tape, + advice_stack, store, advice_map: main_aux_adv_map, }) From b015a2dc0590b21a2fb553980b8279b45e23d121 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:46:02 +0100 Subject: [PATCH 06/19] chore: address feedback and add fix to randomness generator --- stdlib/asm/crypto/stark/random_coin.masm | 37 +++++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/stdlib/asm/crypto/stark/random_coin.masm b/stdlib/asm/crypto/stark/random_coin.masm index 3bf36227db..63fe259c9f 100644 --- a/stdlib/asm/crypto/stark/random_coin.masm +++ b/stdlib/asm/crypto/stark/random_coin.masm @@ -170,13 +170,17 @@ export.init_seed ## 2. num auxiliary segments, which always 1 ## 3. auxiliary segment width ## 4. number of auxiliary random values - ## 5. trace length - push.1174472464 + ## 5. trace length (this is already on the stack) + + ## main segment width is 70 and there are 1 auxiliary segments + ## of width 7 using 16 random extension field elements + push.0x46010710 ## field modulus bytes (2 field elements) - push.1 - push.4294967295 + push.0x01 # lower half of the modulus + push.0xffffffff # upper half of the modulus ## field extension and FRI parameters - push.132103 + ## field extension degree || FRI folding factor || FRI remainder polynomial max degree + push.0x020407 # Hash proof context # Cycles: 15 @@ -661,7 +665,15 @@ export.generate_list_indices exec.get_rate_2 hperm - exec.rpo::squeeze_digest + # Save the new state + exec.constants::r2_ptr mem_storew + dropw + # => [R1, C] + exec.constants::r1_ptr mem_storew + swapw + # => [C, R1] + exec.constants::c_ptr mem_storew + dropw #=> [R1, query_ptr, mask, depth, num_queries, ...] @@ -694,8 +706,17 @@ export.generate_list_indices exec.get_rate_2 hperm - exec.rpo::squeeze_digest - #=> [R1, query_ptr, mask, depth, num_queries, ...] + # Save the new state + exec.constants::r2_ptr mem_storew + dropw + # => [R1, C] + exec.constants::r1_ptr mem_storew + swapw + # => [C, R1] + exec.constants::c_ptr mem_storew + dropw + #=> [R1, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] + movup.7 sub.1 dup movdn.8 push.0 neq end From 511a826c760724add00659ff12e453052d111533 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:37:41 +0100 Subject: [PATCH 07/19] feat: update and sync-up the recursive verifier fix: cleanup and restore security parameters chore: lower num of fri queries and small edits chore: cleanup chore: cleanup --- Cargo.lock | 105 ++++++++++++++------------- core/Cargo.toml | 3 +- processor/src/operations/comb_ops.rs | 4 +- 3 files changed, 59 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0597bccfcf..d7614ab2d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1045,16 +1045,15 @@ dependencies = [ "num-traits", "parking_lot", "proptest", - "winter-math", + "winter-math 0.11.0", "winter-rand-utils", - "winter-utils", + "winter-utils 0.11.0", ] [[package]] name = "miden-crypto" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74af93a5640786def85a08a1fc25e02d8681ed0449ffb4898f4832a5fa08958" +version = "0.12.0" +source = "git+https://github.com/0xPolygonMiden/crypto/?branch=al-fix-rpo-randcoin#067c305f0c02b8535deb066a58e9305912364b07" dependencies = [ "blake3", "cc", @@ -1064,10 +1063,9 @@ dependencies = [ "rand", "rand_core", "sha3", - "thiserror 2.0.3", - "winter-crypto", - "winter-math", - "winter-utils", + "winter-crypto 0.10.2", + "winter-math 0.10.2", + "winter-utils 0.10.2", ] [[package]] @@ -1087,7 +1085,7 @@ checksum = "04742d5184bd76e7b92afcd9ca36b7c587a555d5fc4b27bb8f9d64ac57151f9c" dependencies = [ "metal", "once_cell", - "winter-math", + "winter-math 0.11.0", ] [[package]] @@ -1144,7 +1142,7 @@ dependencies = [ "tracing", "winter-fri", "winter-prover", - "winter-utils", + "winter-utils 0.11.0", ] [[package]] @@ -1699,7 +1697,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -2140,16 +2138,7 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" -dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl", ] [[package]] @@ -2163,17 +2152,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thiserror-impl" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "thread_local" version = "1.1.8" @@ -2277,7 +2255,7 @@ checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" dependencies = [ "ansi_term", "smallvec", - "thiserror 1.0.69", + "thiserror", "tracing", "tracing-subscriber", ] @@ -2768,10 +2746,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8fdb702503625f54dcaf9222aa2c7a0b2e868b3eb84b90d1837d68034bf999" dependencies = [ "libm", - "winter-crypto", + "winter-crypto 0.11.0", "winter-fri", - "winter-math", - "winter-utils", + "winter-math 0.11.0", + "winter-utils 0.11.0", +] + +[[package]] +name = "winter-crypto" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fcae1ada055aa10554910ecffc106cb116a19dba11ac91390ef982f94adb9c5" +dependencies = [ + "blake3", + "sha3", + "winter-math 0.10.2", + "winter-utils 0.10.2", ] [[package]] @@ -2782,8 +2772,8 @@ checksum = "67c57748fd2da77742be601f03eda639ff6046879738fd1faae86e80018263cb" dependencies = [ "blake3", "sha3", - "winter-math", - "winter-utils", + "winter-math 0.11.0", + "winter-utils 0.11.0", ] [[package]] @@ -2792,9 +2782,18 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9f999bc248c6254138b627035cb6d2c319580eb37dadcab6672298dbf00e41" dependencies = [ - "winter-crypto", - "winter-math", - "winter-utils", + "winter-crypto 0.11.0", + "winter-math 0.11.0", + "winter-utils 0.11.0", +] + +[[package]] +name = "winter-math" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82479f94efc0b5374a93e2074ba46ef404384fb1ea6e35a847febec53096509b" +dependencies = [ + "winter-utils 0.10.2", ] [[package]] @@ -2803,7 +2802,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6020c17839fa107ce4a7cc178e407ebbc24adfac1980f4fa2111198e052700ab" dependencies = [ - "winter-utils", + "winter-utils 0.11.0", ] [[package]] @@ -2824,11 +2823,11 @@ checksum = "b6c2f3cf80955f084fd614c86883195331116b6c96dc88532d43d6836bd7adee" dependencies = [ "tracing", "winter-air", - "winter-crypto", + "winter-crypto 0.11.0", "winter-fri", - "winter-math", + "winter-math 0.11.0", "winter-maybe-async", - "winter-utils", + "winter-utils 0.11.0", ] [[package]] @@ -2838,9 +2837,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "226e4c455f6eb72f64ac6eeb7642df25e21ff2280a4f6b09db75392ad6b390ef" dependencies = [ "rand", - "winter-utils", + "winter-utils 0.11.0", ] +[[package]] +name = "winter-utils" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f948e71ffd482aa13d0ec3349047f81ecdb89f3b3287577973dcbf092a25fb4" + [[package]] name = "winter-utils" version = "0.11.0" @@ -2857,10 +2862,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56d949eab6c26328733477ec56ca054fdc69c0c1b8267fa03d8b618ffe2193c4" dependencies = [ "winter-air", - "winter-crypto", + "winter-crypto 0.11.0", "winter-fri", - "winter-math", - "winter-utils", + "winter-math 0.11.0", + "winter-utils 0.11.0", ] [[package]] diff --git a/core/Cargo.toml b/core/Cargo.toml index 8643a81ba9..adc6d22958 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -34,7 +34,8 @@ std = [ lock_api = { version = "0.4", features = ["arc_lock"] } math = { package = "winter-math", version = "0.11", default-features = false } memchr = { version = "2.7", default-features = false } -miden-crypto = { version = "0.13", default-features = false } +#miden-crypto = { version = "0.13", default-features = false } +miden-crypto = { git = "https://github.com/0xPolygonMiden/crypto/", branch ="al-fix-rpo-randcoin", default-features = false } miden-formatting = { version = "0.1", default-features = false } miette = { package = "miden-miette", version = "7.1", default-features = false, optional = true, features = [ "fancy-no-syscall", diff --git a/processor/src/operations/comb_ops.rs b/processor/src/operations/comb_ops.rs index 498026f038..aab8c70468 100644 --- a/processor/src/operations/comb_ops.rs +++ b/processor/src/operations/comb_ops.rs @@ -362,10 +362,10 @@ mod tests { expected.extend_from_slice(&[ZERO, Felt::from(18_u8), Felt::from(10_u8), Felt::from(2_u8)]); // updated accumulators expected.extend_from_slice(&[ - r.to_base_elements()[0], - r.to_base_elements()[1], p.to_base_elements()[0], p.to_base_elements()[1], + r.to_base_elements()[0], + r.to_base_elements()[1], ]); // the top 8 stack elements should equal tx since 8 calls to `rcomb_base` implies 8 circular // shifts of the top 8 elements i.e., the identity map on the top 8 element. From a86b0c5108d58218107d778567336144f923f039 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:58:49 +0100 Subject: [PATCH 08/19] wip --- Cargo.lock | 24 +- Cargo.toml | 14 + air/src/options.rs | 9 +- core/src/lib.rs | 1 + processor/src/stack/mod.rs | 3 + prover/Cargo.toml | 3 + prover/src/lib.rs | 6 +- stdlib/Cargo.toml | 3 + stdlib/tests/crypto/fri/mod.rs | 8 +- stdlib/tests/crypto/fri/verifier_fri_e2f4.rs | 12 +- stdlib/tests/crypto/stark/mod.rs | 790 +++++++++++++++++- .../stark/verifier_recursive/channel.rs | 5 + .../crypto/stark/verifier_recursive/mod.rs | 3 + 13 files changed, 860 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7614ab2d7..33c9f3e70f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1053,7 +1053,6 @@ dependencies = [ [[package]] name = "miden-crypto" version = "0.12.0" -source = "git+https://github.com/0xPolygonMiden/crypto/?branch=al-fix-rpo-randcoin#067c305f0c02b8535deb066a58e9305912364b07" dependencies = [ "blake3", "cc", @@ -1061,6 +1060,7 @@ dependencies = [ "num", "num-complex", "rand", + "rand_chacha", "rand_core", "sha3", "winter-crypto 0.10.2", @@ -1154,7 +1154,9 @@ dependencies = [ "miden-gpu", "miden-processor", "pollster", + "rand_chacha", "tracing", + "winter-air", "winter-maybe-async", "winter-prover", ] @@ -1174,10 +1176,12 @@ dependencies = [ "num-bigint", "pretty_assertions", "rand", + "rand_chacha", "serde_json", "sha2", "sha3", "winter-air", + "winter-crypto", "winter-fri", ] @@ -2745,6 +2749,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8fdb702503625f54dcaf9222aa2c7a0b2e868b3eb84b90d1837d68034bf999" dependencies = [ + "libc-print", "libm", "winter-crypto 0.11.0", "winter-fri", @@ -2759,6 +2764,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fcae1ada055aa10554910ecffc106cb116a19dba11ac91390ef982f94adb9c5" dependencies = [ "blake3", + "rand", + "rand_chacha", "sha3", "winter-math 0.10.2", "winter-utils 0.10.2", @@ -2821,6 +2828,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c2f3cf80955f084fd614c86883195331116b6c96dc88532d43d6836bd7adee" dependencies = [ + "libc-print", + "rand", + "rand_chacha", "tracing", "winter-air", "winter-crypto 0.11.0", @@ -2861,6 +2871,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56d949eab6c26328733477ec56ca054fdc69c0c1b8267fa03d8b618ffe2193c4" dependencies = [ + "libc-print", "winter-air", "winter-crypto 0.11.0", "winter-fri", @@ -2868,6 +2879,17 @@ dependencies = [ "winter-utils 0.11.0", ] +[[package]] +name = "winterfell" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c8336dc6a035698780b8cc624f875e479bd6bf6e1846670f3ef4485c125882" +dependencies = [ + "winter-air", + "winter-prover", + "winter-verifier", +] + [[package]] name = "yansi" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 30d5cdbdff..354eea6ac5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,3 +32,17 @@ inherits = "release" debug = true debug-assertions = true overflow-checks = true + + +[patch.crates-io] +winter-air = {path = "../../training/test_task/winterfell/air" } +winter-crypto = {path = "../../training/test_task/winterfell/crypto" } +winter-prover = {path = "../../training/test_task/winterfell/prover" } +winter-verifier = {path = "../../training/test_task/winterfell/verifier" } +winter-math = {path = "../../training/test_task/winterfell/math" } +winter-fri = {path = "../../training/test_task/winterfell/fri" } +winter-maybe-async = {path = "../../training/test_task/winterfell/utils/maybe_async" } +winter-utils = {path = "../../training/test_task/winterfell/utils/core" } +winter-rand-utils = {path = "../../training/test_task/winterfell/utils/rand" } + +miden-crypto = {path = "../../work/crypto" } diff --git a/air/src/options.rs b/air/src/options.rs index fbbbbb31ce..74cce837ff 100644 --- a/air/src/options.rs +++ b/air/src/options.rs @@ -19,19 +19,19 @@ impl ProvingOptions { /// Standard proof parameters for 96-bit conjectured security in non-recursive context. pub const REGULAR_96_BITS: WinterProofOptions = - WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 8, 255); + WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 8, 255, false); /// Standard proof parameters for 128-bit conjectured security in non-recursive context. pub const REGULAR_128_BITS: WinterProofOptions = - WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 8, 255); + WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 8, 255, false); /// Standard proof parameters for 96-bit conjectured security in recursive context. pub const RECURSIVE_96_BITS: WinterProofOptions = - WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 4, 7); + WinterProofOptions::new(11, 8, 12, FieldExtension::Quadratic, 4, 7, false); /// Standard proof parameters for 128-bit conjectured security in recursive context. pub const RECURSIVE_128_BITS: WinterProofOptions = - WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 4, 7); + WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 4, 7, false); // CONSTRUCTORS // -------------------------------------------------------------------------------------------- @@ -53,6 +53,7 @@ impl ProvingOptions { field_extension, fri_folding_factor, fri_remainder_max_degree, + false, ); let exec_options = ExecutionOptions::default(); Self { exec_options, proof_options, hash_fn } diff --git a/core/src/lib.rs b/core/src/lib.rs index 650c726573..1f981c50d5 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -85,6 +85,7 @@ pub mod crypto { pub mod dsa { pub use miden_crypto::dsa::rpo_falcon512; + pub use miden_crypto::dsa::rpo_stark; } } diff --git a/processor/src/stack/mod.rs b/processor/src/stack/mod.rs index ad133e48cb..a8979f09a1 100644 --- a/processor/src/stack/mod.rs +++ b/processor/src/stack/mod.rs @@ -1,3 +1,5 @@ +use std::println; + use alloc::vec::Vec; use miden_air::RowIndex; @@ -133,6 +135,7 @@ impl Stack { /// # Errors /// Returns an error if the overflow table is not empty at the current clock cycle. pub fn build_stack_outputs(&self) -> Result { + println!("stak is {:?}", self.get_state_at(self.clk)); if self.overflow.num_active_rows() != 0 { return Err(ExecutionError::OutputStackOverflow(self.overflow.num_active_rows())); } diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 2dc9f783a5..7440b482a8 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -27,6 +27,9 @@ tracing = { version = "0.1", default-features = false, features = ["attributes"] winter-maybe-async = { package = "winter-maybe-async", version = "0.11", default-features = false } winter-prover = { package = "winter-prover", version = "0.11", default-features = false } +winter-air = { version = "0.10", default-features = false } +rand_chacha = { version = "0.3", default-features = false } + [target.'cfg(all(target_arch = "aarch64", target_os = "macos"))'.dependencies] elsa = { version = "1.9", optional = true } miden-gpu = { version = "0.4", optional = true } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 25fb837dbd..34c39bd367 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -19,7 +19,9 @@ use processor::{ math::{Felt, FieldElement}, ExecutionTrace, Program, }; +use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use tracing::instrument; +use winter_air::ZkParameters; use winter_maybe_async::{maybe_async, maybe_await}; use winter_prover::{ matrix::ColMatrix, CompositionPoly, CompositionPolyTrace, ConstraintCompositionCoefficients, @@ -219,8 +221,10 @@ where main_trace: &ColMatrix, domain: &StarkDomain, partition_options: PartitionOptions, + zk_parameters: Option ) -> (Self::TraceLde, TracePolyTable) { - DefaultTraceLde::new(trace_info, main_trace, domain, partition_options) + let mut prng = ChaCha20Rng::from_entropy(); + DefaultTraceLde::new(trace_info, main_trace, domain, partition_options, zk_parameters, &mut prng) } #[maybe_async] diff --git a/stdlib/Cargo.toml b/stdlib/Cargo.toml index 5d35ff006e..4db773c57a 100644 --- a/stdlib/Cargo.toml +++ b/stdlib/Cargo.toml @@ -51,6 +51,9 @@ test-utils = { package = "miden-test-utils", path = "../test-utils" } vm-core = { package = "miden-core", path = "../core", version = "0.11", default-features = false } winter-air = { package = "winter-air", version = "0.11" } winter-fri = { package = "winter-fri", version = "0.11" } +winter-crypto = { package = "winter-crypto", version = "0.13" } +rand_chacha = { version = "0.3", default-features = false } + [build-dependencies] assembly = { package = "miden-assembly", path = "../assembly", version = "0.11" } diff --git a/stdlib/tests/crypto/fri/mod.rs b/stdlib/tests/crypto/fri/mod.rs index 106bf8f05c..f8fc6d7899 100644 --- a/stdlib/tests/crypto/fri/mod.rs +++ b/stdlib/tests/crypto/fri/mod.rs @@ -1,7 +1,7 @@ use alloc::collections::BTreeMap; -use processor::Digest; -use test_utils::{crypto::MerkleStore, Felt, StarkField}; +use processor::{crypto::Rpo256, Digest}; +use test_utils::{crypto::MerkleStore, Felt, MerkleTreeVC, StarkField}; mod channel; @@ -34,7 +34,7 @@ fn fri_fold4_ext2_remainder32() { commitments, remainder, num_queries, - } = fri_prove_verify_fold4_ext2(trace_len_e).unwrap(); + } = fri_prove_verify_fold4_ext2::>(trace_len_e).unwrap(); let advice_stack = prepare_advice_stack( depth, @@ -82,7 +82,7 @@ fn fri_fold4_ext2_remainder64() { commitments, remainder, num_queries, - } = fri_prove_verify_fold4_ext2(trace_len_e).unwrap(); + } = fri_prove_verify_fold4_ext2::>(trace_len_e).unwrap(); let advice_stack = prepare_advice_stack( depth, diff --git a/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs b/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs index ca4acb420f..911c23db34 100644 --- a/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs +++ b/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs @@ -4,12 +4,15 @@ use processor::{ crypto::{Hasher, RandomCoin, RpoDigest, WinterRandomCoin}, Digest as MidenDigest, }; +use rand::SeedableRng; +use rand_chacha::ChaCha20Rng; use test_utils::{ crypto::{MerklePath, NodeIndex, PartialMerkleTree, Rpo256 as MidenHasher}, group_slice_elements, math::fft, Felt, FieldElement, MerkleTreeVC, QuadFelt as QuadExt, StarkField, EMPTY_WORD, }; +use winter_crypto::VectorCommitment; use winter_fri::{ folding::fold_positions, DefaultProverChannel, FriOptions, FriProof, FriProver, VerifierError, }; @@ -52,7 +55,7 @@ pub struct FriResult { // The main purpose of this function is to build the non-deterministic inputs needed to verify // a FRI proof inside the Miden VM. // The output is organized as follows: -pub fn fri_prove_verify_fold4_ext2(trace_length_e: usize) -> Result { +pub fn fri_prove_verify_fold4_ext2>(trace_length_e: usize) -> Result { let max_remainder_size_e = 3; let folding_factor_e = 2; let trace_length = 1 << trace_length_e; @@ -60,14 +63,15 @@ pub fn fri_prove_verify_fold4_ext2(trace_length_e: usize) -> Result>::new(options.clone()); - prover.build_layers(&mut channel, evaluations.clone()); + let mut prover = FriProver::<_, _, _, VC>::new(options.clone()); + prover.build_layers(&mut channel, evaluations.clone(), &mut prng); let positions = channel.draw_query_positions(nonce); let proof = prover.build_proof(&positions); @@ -123,7 +127,7 @@ pub fn build_prover_channel( trace_length: usize, options: &FriOptions, ) -> DefaultProverChannel> { - DefaultProverChannel::new(trace_length * options.blowup_factor(), 32) + DefaultProverChannel::new(trace_length * options.blowup_factor(), 32, false) } pub fn build_evaluations(trace_length: usize, lde_blowup: usize) -> Vec { diff --git a/stdlib/tests/crypto/stark/mod.rs b/stdlib/tests/crypto/stark/mod.rs index c72d725158..0371cbf5bf 100644 --- a/stdlib/tests/crypto/stark/mod.rs +++ b/stdlib/tests/crypto/stark/mod.rs @@ -1,15 +1,68 @@ -mod verifier_recursive; use assembly::Assembler; -use miden_air::{FieldExtension, HashFunction, PublicInputs}; -use processor::{DefaultHost, Program, ProgramInfo}; +use miden_air::{Felt, FieldElement, FieldExtension, HashFunction, PublicInputs}; +use num::traits::sign; +use processor::{DefaultHost, Program, ProgramInfo, Word}; +use rand::SeedableRng; +use rand_chacha::ChaCha20Rng; +use signature::{generate_advice_inputs_signature, VerifierData}; use test_utils::{ - prove, AdviceInputs, MemAdviceProvider, ProvingOptions, StackInputs, VerifierError, + crypto::{rpo_falcon512::PublicKey, rpo_stark::{PublicInputs as SignaturePublicInputs, SecretKey}}, math::{polynom, ExtensionOf}, prove, rand::{rand_array, rand_value}, verify, AdviceInputs, MemAdviceProvider, ProvingOptions, QuadFelt, StackInputs, VerifierError }; -use verifier_recursive::{generate_advice_inputs, VerifierData}; + + +mod verifier_recursive; +use verifier_recursive::{generate_advice_inputs, to_int_vec, QuadExt, }; + +mod signature; + + + +// Note: Changes to MidenVM may cause this test to fail when some of the assumptions documented +// in `stdlib/asm/crypto/stark/verifier.masm` are violated. +#[test] +#[ignore] +fn signature_verification() { + + let VerifierData { initial_stack, tape, store, advice_map } = + generate_signature_data().unwrap(); + + // Verify inside Miden VM + let source = " + use.std::crypto::dsa::rpo_stark::verifier + begin + exec.verifier::verify + end + "; + + let test = build_test!(source, &initial_stack, &tape, store, advice_map); + + test.expect_stack(&[]); +} + +fn generate_signature_data() -> Result { + let seed = [0_u8; 32]; + let mut rng = ChaCha20Rng::from_seed(seed); + let sk = SecretKey::with_rng(&mut rng); + let sk = SecretKey::from_word(Word::default()); + + let message = Word::default(); + let signature = sk.sign(message); +//println!("signature {:?}", signature); + let pk = sk.compute_public_key(); + // signature.verify(message, pk.inner()); + let proof = signature.inner(); + + let pub_inputs = SignaturePublicInputs::new(pk.inner(), message); + + let res = generate_advice_inputs_signature(proof, pub_inputs); + // println!("res is {:?}", res); + Ok(res.unwrap()) +} // Note: Changes to MidenVM may cause this test to fail when some of the assumptions documented // in `stdlib/asm/crypto/stark/verifier.masm` are violated. #[test] +#[ignore] fn stark_verifier_e2f4() { // An example MASM program to be verified inside Miden VM. // Note that output stack-overflow is not yet supported because of the way we handle public @@ -56,14 +109,737 @@ pub fn generate_recursive_verifier_data( let mut host = DefaultHost::new(advice_provider); let options = - ProvingOptions::new(27, 8, 12, FieldExtension::Quadratic, 4, 7, HashFunction::Rpo256); + ProvingOptions::new(11, 8, 12, FieldExtension::Quadratic, 4, 7, HashFunction::Rpo256); let (stack_outputs, proof) = prove(&program, stack_inputs.clone(), &mut host, options).unwrap(); let program_info = ProgramInfo::from(program); - + let res = + verify(program_info.clone(), stack_inputs.clone(), stack_outputs.clone(), proof.clone()) + .unwrap(); + println!("res of veri {:?}", res); // build public inputs and generate the advice data needed for recursive proof verification let pub_inputs = PublicInputs::new(program_info, stack_inputs, stack_outputs); + let (_, proof) = proof.into_parts(); Ok(generate_advice_inputs(proof, pub_inputs).unwrap()) } + +/* +poly 0 at (14281334308168704527, 10495222116659147228) is (10060846794257653263, 546027550684353096) +poly 1 at (14281334308168704527, 10495222116659147228) is (10903134704496183277, 5579342745194126910) +poly 2 at (14281334308168704527, 10495222116659147228) is (12893269862983042775, 17647699874671928675) +poly 3 at (14281334308168704527, 10495222116659147228) is (11122676875213712094, 5263064823292274143) +poly 4 at (14281334308168704527, 10495222116659147228) is (41855652377006736, 9909668281301462903) +poly 5 at (14281334308168704527, 10495222116659147228) is (14932615313904988467, 7592103672217106309) +poly 6 at (14281334308168704527, 10495222116659147228) is (20740824113534935, 3818898257924990209) +poly 7 at (14281334308168704527, 10495222116659147228) is (15272117991568816033, 14472765353298605242) +poly 8 at (14281334308168704527, 10495222116659147228) is (1409366930799599557, 4944651295747950778) +poly 9 at (14281334308168704527, 10495222116659147228) is (15967857750552075868, 2857971283248518823) +poly 10 at (14281334308168704527, 10495222116659147228) is (11602683508887447121, 18097224529377507115) +poly 11 at (14281334308168704527, 10495222116659147228) is (6426931889180492583, 17042609443108091430) +poly 12 at (14281334308168704527, 10495222116659147228) is (3787620295263208906, 5581463112448029526) +poly 13 at (14281334308168704527, 10495222116659147228) is (14819709244247351689, 9116944519363158237) +poly 14 at (14281334308168704527, 10495222116659147228) is (18258588819309979526, 12167294900610607376) +poly 15 at (14281334308168704527, 10495222116659147228) is (13323880019629950849, 16070006070861920166) +poly 16 at (14281334308168704527, 10495222116659147228) is (15088898314701251493, 17537315582941049748) +poly 17 at (14281334308168704527, 10495222116659147228) is (601580842485586130, 9327490444933127718) +poly 18 at (14281334308168704527, 10495222116659147228) is (2822984643375099546, 7202787223205524049) +poly 19 at (14281334308168704527, 10495222116659147228) is (14598635898512929731, 4144988733395143778) +poly 20 at (14281334308168704527, 10495222116659147228) is (17626662679135368322, 1223116119813894249) +poly 21 at (14281334308168704527, 10495222116659147228) is (4860278503993160809, 7161649524312813954) +poly 22 at (14281334308168704527, 10495222116659147228) is (5189975042430731858, 9217744093123510922) +poly 23 at (14281334308168704527, 10495222116659147228) is (3964029779034283138, 11151025876422081715) + +*/ + + +#[test] +fn second_mds_multiply() { + // Verify inside Miden VM + let source = " + use.std::crypto::dsa::rpo_stark::rpo_stark + begin + push.1000 + push.2.0.2.0 + repeat.3 + dup.4 add.1 swap.5 + mem_storew + end + + dropw + push.1.0.1.0 + repeat.3 + dup.4 add.1 swap.5 + mem_storew + end + + dropw drop + + push.14281334308168704527 push.10495222116659147228 + push.2000 push.1000 + exec.rpo_stark::multiply_mds_add_constant_apply_sbox_round + + add.2000 swap + + exec.rpo_stark::multiply_mds_add_constant + + push.3000 + padw + repeat.6 + dup.4 add.1 swap.5 + mem_loadw + movup.4 + padw + end + + + end + "; + + + let z = QuadExt::new(Felt::new(14281334308168704527), Felt::new(10495222116659147228)); + let mut ark = vec![]; + + for poly in ark1_polys { + let poly: Vec = poly + .iter() + .map(|coef| { + Felt::new(*coef) + + }) + .collect(); + let eval = polynom::eval(&poly, z); + + ark.push(eval); + } + //ark.reverse(); + let mut state: [QuadExt; 12] = [QuadExt::ONE; 12]; + state.iter_mut().take(6).for_each(|s| *s = s.double() ); + println!("state is {:?}", state); + //let mut initial_state = state.clone(); + apply_mds(&mut state); + add_constants(&mut state, &ark); + apply_sbox(&mut state); + + + let mut ark = vec![]; + + for poly in ark2_polys { + let poly: Vec = poly + .iter() + .map(|coef| { + Felt::new(*coef) + + }) + .collect(); + let eval = polynom::eval(&poly, z); + + ark.push(eval); + } + + apply_mds(&mut state); + add_constants(&mut state, &ark); + + let mut input_stack = vec![]; + input_stack.push(14281334308168704527_u64); + input_stack.push(10495222116659147228); + + //initial_state.reverse(); + //let tmp = to_int_vec( &initial_state) ; + + //let mut adv_stack = vec![]; + //adv_stack.extend_from_slice(&tmp); + + let test = build_test!(source, &[] ); + + + println!("res is {:?}", ark); + println!("state is {:?}", state); + test.expect_stack(&[]); +} +#[test] +fn multiply_mds_add_constant_apply_sbox_round() { + // Verify inside Miden VM + let source = " + use.std::crypto::dsa::rpo_stark::rpo_stark + begin + push.1000 + push.2.0.2.0 + repeat.3 + dup.4 add.1 swap.5 + mem_storew + end + + dropw + push.1.0.1.0 + repeat.3 + dup.4 add.1 swap.5 + mem_storew + end + + dropw drop + + push.14281334308168704527 push.10495222116659147228 + push.2000 push.1000 + exec.rpo_stark::multiply_mds_add_constant_apply_sbox_round + + push.2000 + padw + repeat.6 + dup.4 add.1 swap.5 + mem_loadw + movup.4 + padw + end + + + end + "; + + + let z = QuadExt::new(Felt::new(14281334308168704527), Felt::new(10495222116659147228)); + let mut ark = vec![]; + + for poly in ark1_polys { + let poly: Vec = poly + .iter() + .map(|coef| { + Felt::new(*coef) + + }) + .collect(); + let eval = polynom::eval(&poly, z); + + ark.push(eval); + } + //ark.reverse(); + let mut state: [QuadExt; 12] = [QuadExt::ONE; 12]; + state.iter_mut().take(6).for_each(|s| *s = s.double() ); + println!("state is {:?}", state); + //let mut initial_state = state.clone(); + apply_mds(&mut state); + add_constants(&mut state, &ark); + apply_sbox(&mut state); + + let mut input_stack = vec![]; + input_stack.push(14281334308168704527_u64); + input_stack.push(10495222116659147228); + + //initial_state.reverse(); + //let tmp = to_int_vec( &initial_state) ; + + //let mut adv_stack = vec![]; + //adv_stack.extend_from_slice(&tmp); + + let test = build_test!(source, &[] ); + + + println!("res is {:?}", ark); + println!("state is {:?}", state); + test.expect_stack(&[]); +} + +#[test] +fn multiply_double_extension_by_base() { + // Verify inside Miden VM + let source = " + use.std::crypto::dsa::rpo_stark::rpo_stark + begin + exec.rpo_stark::multiply_double_extension_by_base + end + "; + + let tau0 = rand_value::(); + let tau1 = rand_value::(); + let k0: Felt = rand_value(); + let k1: Felt = rand_value(); + let res0 = tau0.mul_base(k0); + let res1 = tau1.mul_base(k1); + let input_stack = vec![ + tau0.base_element(0).as_int(), + tau0.base_element(1).as_int(), + tau1.base_element(0).as_int(), + tau1.base_element(1).as_int(), + k0.as_int(), + k1.as_int(), + ]; + + let res = res0 + res1; + let output_stack = vec![res.base_element(1).as_int(), res.base_element(0).as_int()]; + + let test = build_test!(source, &input_stack); + test.expect_stack(&output_stack); +} + +#[test] +fn sbox() { + // Verify inside Miden VM + let source = " + use.std::crypto::dsa::rpo_stark::rpo_stark + begin + exec.rpo_stark::sbox + end + "; + + let tau = rand_value::(); + + let input_stack = vec![tau.base_element(0).as_int(), tau.base_element(1).as_int()]; + + let res = tau.exp((7_u32).into()); + let output_stack = vec![res.base_element(1).as_int(), res.base_element(0).as_int()]; + + let test = build_test!(source, &input_stack); + test.expect_stack(&output_stack); +} + +/* +coef is 8329032129963563016 +acc is (0, 0) +res is (8329032129963563016, 0) +coef is 8934619293596015107 +acc is (8329032129963563016, 0) +res is (5357259674621098529, 0) +coef is 15061243612815629935 +acc is (5357259674621098529, 0) +res is (18043538241885439730, 0) +coef is 17197876067442802066 +acc is (18043538241885439730, 0) +res is (15585052757326223702, 0) +coef is 16438925404421745533 +acc is (15585052757326223702, 0) +res is (4992160156068303057, 0) +coef is 3323980907020445132 +acc is (4992160156068303057, 0) +res is (4845877461879073039, 0) +coef is 15627700026530187867 +acc is (4845877461879073039, 0) +res is (16564465804631895702, 0) +coef is 2791148843003040487 +acc is (16564465804631895702, 0) +res is (13708779853286870332, 0) +poly 0 at (5904545740857336763, 2641448861188835256) is (13708779853286870332, 0) + +*/ +#[test] +fn evaluate_ark1_index_0_at_z() { + let source = " + use.std::crypto::dsa::rpo_stark::round_constants + begin + # => [tau1, tau0, dest_ptr, dest_ptr, ...] + + exec.round_constants::evaluate_ark1_index_0_at_z + # => [tau1, tau0, dest_ptr + 1, dest_ptr, ...] + + # Load the computed evaluation at tau + padw movup.7 mem_loadw + # => [0, 0, ev1, ev0, tau1, tau0, dest_ptr + 1, ...] + + # Clean up the stack + drop drop + # => [ev1, ev0, tau1, tau0, dest_ptr + 1, ...] + + # Fix overflow + movup.5 drop + end + "; + + let tau = QuadFelt::new(Felt::new(2358509191725100597), Felt::new(12448696411509285448)); + let ptr = 1000; + let ptr_nxt = 1001; + let res = QuadFelt::new(Felt::new(9108108481109559168), Felt::new(1381914921145369315)); + let input_stack = vec![ptr, ptr, tau.base_element(0).as_int(), tau.base_element(1).as_int()]; + + let output_stack = vec![ + res.base_element(1).as_int(), + res.base_element(0).as_int(), + tau.base_element(1).as_int(), + tau.base_element(0).as_int(), + ptr_nxt, + ]; + + let test = build_test!(source, &input_stack); + test.expect_stack(&output_stack); +} + +#[test] +fn evaluate_ark1_index_1_at_z() { + let source = " + use.std::crypto::dsa::rpo_stark::round_constants + begin + # => [tau1, tau0, dest_ptr, dest_ptr, ...] + + exec.round_constants::evaluate_ark1_index_1_at_z + # => [tau1, tau0, dest_ptr + 1, dest_ptr, ...] + + # Load the computed evaluation at tau + padw movup.7 mem_loadw + # => [0, 0, ev1, ev0, tau1, tau0, dest_ptr + 1, ...] + + # Clean up the stack + drop drop + # => [ev1, ev0, tau1, tau0, dest_ptr + 1, ...] + + # Fix overflow + movup.5 drop + end + "; + + let tau = QuadFelt::new(Felt::new(14281334308168704527), Felt::new(10495222116659147228)); + let ptr = 1000; + let ptr_nxt = 1001; + let res = QuadFelt::new(Felt::new(10903134704496183277), Felt::new(5579342745194126910)); + let input_stack = vec![ptr, ptr, tau.base_element(0).as_int(), tau.base_element(1).as_int()]; + + let output_stack = vec![ + res.base_element(1).as_int(), + res.base_element(0).as_int(), + tau.base_element(1).as_int(), + tau.base_element(0).as_int(), + ptr_nxt, + ]; + + let test = build_test!(source, &input_stack); + test.expect_stack(&output_stack); +} + +const ark1_polys: [[u64; 8]; 12] = [ + [ + 2791148843003040487, + 15627700026530187867, + 3323980907020445132, + 16438925404421745533, + 17197876067442802066, + 15061243612815629935, + 8934619293596015107, + 8329032129963563016, + ], + [ + 12374840782518234980, + 13067814063463246108, + 16444767378767684843, + 14102478245486764913, + 5721113686559987364, + 5550835267666484285, + 1140255260049705235, + 2940403776379367555, + ], + [ + 803239822289277331, + 92290315131409452, + 14504533961394498192, + 17449340622223708244, + 11641839262529699117, + 13830007435883778192, + 2171477269448177901, + 18024172012126180450, + ], + [ + 17259550729090128080, + 1436126261944143983, + 6827772059756176056, + 13633102721671278493, + 438808730725699483, + 5407974288453498850, + 8312944094443125539, + 12083646389987382742, + ], + [ + 16872030888212246909, + 10307413365916228519, + 5970696349452178882, + 3075676239487301499, + 6764475190363405683, + 12388465667776429451, + 5463940702410555170, + 4302341177141596798, + ], + [ + 13010646010715444756, + 13220880625440862351, + 15043202536693295725, + 12450612311725651741, + 1975121089721419805, + 17751579298152306599, + 5865829689316994740, + 10135856292008745804, + ], + [ + 11079243880688886569, + 13171475342452126305, + 16717118787075991203, + 12997762624630485971, + 2082764394649465048, + 2274009722649114980, + 11078166678912510243, + 14537022526074710084, + ], + [ + 6412175863526823473, + 7693358564819205804, + 12953861830888836611, + 942265184773461437, + 1607941585775238966, + 4379845611455349528, + 58856250008039951, + 16473125605159627119, + ], + [ + 5005263760224338834, + 11877952992388592984, + 13609269279460528668, + 12700182930600529552, + 13020259874513262126, + 1930782708828158469, + 5575776764248027070, + 12391274268940303373, + ], + [ + 11718820523788741765, + 59883440729546652, + 6312723811819661455, + 5308884009005395250, + 6182287153329169016, + 13207315343261220442, + 4815800570707034136, + 8349688098368982860, + ], + [ + 6043410183720093018, + 2126146309185433854, + 8378524768105627493, + 5544949132734068891, + 17681500018572116275, + 10699876530722034865, + 8011357321704081273, + 5725123156318075397, + ], + [ + 6223946836251310965, + 16586492306509623392, + 6856802671405566180, + 16479930990938214663, + 13641986601858015391, + 6665166827227923662, + 9454375281307822385, + 8412441953430543726, + ], +]; + + +const ark2_polys: [[u64; 8]; 12] = [[4644899059340455409, 2588000450744117712, 13105238537181697838, 9145530290182703923, 8318881075359001860, 2260425315804771343, 13140762909627491530, 10125751776384352797], +[1076805373481731514, 731771438168089372, 1451573959488719120, 7220138601034011484, 14518803097042109937, 8441003397118172058, 16691081699485452106, 13848563765445705020], +[10296796646521415185, 5634304416804201670, 2436250166439517097, 175122579984732489, 17819414171265412835, 11568691945480450310, 4685303716418085212, 9212910395839541860], +[13748310607328698306, 3231680637487443842, 11897908975989921011, 14948979053368640201, 788938329072261875, 2424518612267165880, 14447959571237460393, 17817850486374744537], +[430095072692583909, 3538460359490439815, 4910259163119359388, 13172964728236666704, 13264785748607221492, 9148793266208888638, 12523400296259625004, 1323646892185216842], +[17837225074619059476, 6702081431642835557, 15726014635140220142, 14804677398279293696, 17716100798530125807, 12274533074791157450, 454935568758037748, 3171283654084997195], +[2011206516638815708, 12992430013458659144, 8696495089799708930, 1400178508260896298, 4445028994876124043, 15086337211977579054, 2579568427157492470, 3842347926541387017], +[14455558190054243213, 9476151068182324219, 4476065032800445994, 4772948326559040143, 9999073914541559972, 8857261784008983684, 15200374878312346200, 12519281252880051360], +[15872839284583424888, 9158419513185267937, 989723691436384985, 3480674361312569156, 7972171312030024281, 6916765091459382631, 5174110470653655799, 10891579218396689814], +[3270022819064790682, 17115077542742512990, 12665325866539717707, 2141009619237002231, 9832785799742116087, 10808339012888707871, 17545443011752642513, 12528974695128465622], +[8849418171382398211, 1150833344352386619, 6870113859747343930, 13474841269676445703, 12213798227721715260, 12131307142274672056, 11958348010538656609, 6096042974457287451], +[17284012187876944133, 10339865060086263172, 12560365515943446953, 8769164948183307270, 11644987068425776572, 16184522505189623125, 1188079598780402137, 16980889739006603967]]; + +/// RPO MDS matrix +pub const MDS: [[Felt; STATE_WIDTH]; STATE_WIDTH] = [ + [ + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + ], + [ + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + ], + [ + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + ], + [ + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + ], + [ + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + ], + [ + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + ], + [ + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + ], + [ + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + ], + [ + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + Felt::new(26), + ], + [ + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + Felt::new(8), + ], + [ + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + Felt::new(23), + ], + [ + Felt::new(23), + Felt::new(8), + Felt::new(26), + Felt::new(13), + Felt::new(10), + Felt::new(9), + Felt::new(7), + Felt::new(6), + Felt::new(22), + Felt::new(21), + Felt::new(8), + Felt::new(7), + ], +]; + +const STATE_WIDTH:usize = 12; +pub fn add_constants>(state: &mut [E], ark: &[E]) { + + + for i in 0..STATE_WIDTH { + state[i] += ark[i]; + } + +} + + + +#[inline(always)] +fn apply_sbox>(state: &mut [E; STATE_WIDTH]) { + state.iter_mut().for_each(|v| { + let t2 = v.square(); + let t4 = t2.square(); + *v *= t2 * t4; + }); +} + +#[inline(always)] +fn apply_mds>(state: &mut [E; STATE_WIDTH]) { + let mut result = [E::ZERO; STATE_WIDTH]; + result.iter_mut().zip(MDS).for_each(|(r, mds_row)| { + state.iter().zip(mds_row).for_each(|(&s, m)| { + *r += E::from(m) * s; + }); + }); + *state = result +} diff --git a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs index 8a92142064..20539ae348 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs @@ -57,6 +57,7 @@ impl VerifierChannel { pow_nonce, num_unique_queries, gkr_proof: _, + salts, } = proof; // make AIR and proof base fields are the same @@ -282,6 +283,10 @@ impl FriVerifierChannel for VerifierChannel { fn take_fri_remainder(&mut self) -> Vec { self.fri_remainder.take().expect("already read") } + + fn take_salt(&mut self) -> Option<::Digest> { + todo!() + } } // TRACE QUERIES diff --git a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs index 2d59f5119e..6d7cffd284 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs @@ -13,6 +13,8 @@ use winter_fri::VerifierChannel as FriVerifierChannel; mod channel; use channel::VerifierChannel; +use super::signature::VerifierData; + pub const BLOWUP_FACTOR: usize = 8; pub type QuadExt = QuadExtension; @@ -66,6 +68,7 @@ pub fn generate_advice_inputs( // generate the auxiliary random elements let mut aux_trace_rand_elements = vec![]; for commitment in trace_commitments.iter().skip(1) { + println!("aux_trace_com {:?}", commitment); let rand_elements: Vec = air .get_aux_rand_elements(&mut public_coin) .map_err(|_| VerifierError::RandomCoinError)?; From d6a68c3c761184863ee577065226a6e2b0c49f42 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:40:46 +0100 Subject: [PATCH 09/19] wip: verification of signature in masm --- .../asm/crypto/dsa/rpo_stark/constants.masm | 319 +++++++ .../crypto/dsa/rpo_stark/deep_queries.masm | 573 +++++++++++++ stdlib/asm/crypto/dsa/rpo_stark/fri.masm | 221 +++++ .../asm/crypto/dsa/rpo_stark/ood_frames.masm | 202 +++++ .../crypto/dsa/rpo_stark/public_inputs.masm | 36 + .../asm/crypto/dsa/rpo_stark/random_coin.masm | 775 +++++++++++++++++ stdlib/asm/crypto/dsa/rpo_stark/utils.masm | 148 ++++ stdlib/asm/crypto/dsa/rpo_stark/verifier.masm | 187 +++++ stdlib/tests/crypto/fri/verifier_fri_e2f4.rs | 2 +- stdlib/tests/crypto/stark/mod.rs | 784 +----------------- .../stark/verifier_recursive/channel.rs | 2 +- .../crypto/stark/verifier_recursive/mod.rs | 1 - 12 files changed, 2489 insertions(+), 761 deletions(-) create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/constants.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/fri.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/utils.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/verifier.masm diff --git a/stdlib/asm/crypto/dsa/rpo_stark/constants.masm b/stdlib/asm/crypto/dsa/rpo_stark/constants.masm new file mode 100644 index 0000000000..a0419e1a2a --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/constants.masm @@ -0,0 +1,319 @@ +# CONSTANTS +# ================================================================================================= + +# General constants +const.ROOT_UNITY=7277203076849721926 +const.DOMAIN_OFFSET=7 +const.DOMAIN_OFFSET_INV=2635249152773512046 + + +# MEMORY POINTERS +# ================================================================================================= + +# Trace domain generator +const.TRACE_DOMAIN_GENERATOR_PTR=4294799999 + +# Public inputs +const.PUBLIC_INPUTS_PTR=4294800000 + +# OOD Frames +# 12 * 2 * 2 Felt for current and next trace rows and 12 * 2 Felt for constraint composition +# polynomials. Total memory slots required: (12 * 2 * 2 + 12 * 2) / 4 = 18 +const.OOD_TRACE_PTR=4294900000 +const.OOD_CONSTRAINT_EVALS_PTR=4294900012 + +# Current trace row +# 70 Felt for main portion of trace, 7 * 2 Felt for auxiliary portion of trace and 8 * 2 Felt for +# constraint composition polynomials. Since we store these with the padding to make each of the +# three portions a multiple of 8, the number of slots required is (72 + 16 + 16) / 4 = 26 +const.CURRENT_TRACE_ROW_PTR=4294900100 + +# We need 2 Felt for each constraint. We take 2800 slots as an upper bound +const.COMPOSITION_COEF_PTR=4294900200 + +# We need 2 Felt for each trace column and each of the 8 constraint composition columns. We thus need +# (70 + 7 + 8) * 2 Felt i.e. 43 memory slots. +const.DEEP_RAND_CC_PTR=4294903000 + +# FRI +# +# (FRI_COM_PTR - 100) ---| +# . +# . | <- FRI queries +# . +# FRI_COM_PTR ---| +# . +# . | <- FRI layer commitments and folding challenges +# . +# (FRI_COM_PTR + 32) ---| +# . +# . | <- Remainder codeword and polynomial +# . +# (FRI_COM_PTR + 66-1) ---| +# +# For each FRI layer, we need 2 memory slots, one for storing the FRI layer commitment and one for +# storing the word [a0, a1, log2(lde_size), lde_size] where a := (a0, a1) is the folding randomness +# and lde_size is the size of the LDE domain. Since we are using a folding factor of 4 and the +# maximal degree of the remainder polynomial that we allow is 7, an upper limit of 16 FRI layers is +# ample and the number of memory slots we thus allocate for this is 32. Moreover, we allocate +# an additional 32 slots for the remainder codeword and 2 for the remainder polynomial. These are +# expected to be laid out right after the FRI commitments. +# The total number of slots thus becomes 66. +const.FRI_COM_PTR=4294903200 + +# Commitment to main, auxiliary and composition polynomials traces +const.MAIN_TRACE_COM_PTR=4294903300 +const.COMPOSITION_POLY_COM_PTR=4294903301 + +# Instant-specific constants +const.NUM_FRI_QUERIES=100 +const.REMAINDER_CODEWORD_OFFSET=6 +const.LDE_SIZE_PTR=4294903303 +const.Z_PTR=4294903304 +const.NUM_QUERIES_PTR=4294903305 +const.TRACE_LENGTH_PTR=4294903306 +const.TRACE_LENGTH_LOG_PTR=4294903307 +const.GRINDING_FACTOR_PTR=4294903308 + +# RPO capacity initialization words +const.ZERO_WORD_PTR=4294903309 +const.ZERO_ZERO_ZERO_FOUR_PTR=4294903310 + +# State of RPO-based random coin +const.C_PTR=4294903311 +const.R1_PTR=4294903312 +const.R2_PTR=4294903313 + +# Address used for storing temporary values: +const.TMP1=4294903315 +const.TMP2=4294903316 +const.TMP3=4294903317 +const.TMP4=4294903318 +const.TMP5=4294903319 +const.TMP6=4294903320 +const.TMP7=4294903321 +const.TMP8=4294903322 +const.TMP9=4294903323 +const.TMP10=4294903324 +const.TMP11=4294903325 + + + +# The following is a table summarizing the memory pointers used: +# +------------------------------------------+-------------------------+ +# | ID | Address | +# +------------------------------------------+-------------------------+ +# | TRACE_DOMAIN_GENERATOR_PTR | 4294799999 | +# | PUBLIC_INPUTS_PTR | 4294800000 | +# | OOD_TRACE_PTR | 4294900000 | +# | OOD_CONSTRAINT_EVALS_PTR | 4294900077 | +# | CURRENT_TRACE_ROW_PTR | 4294900100 | +# | AUX_RAND_ELEM_PTR | 4294900150 | +# | COMPOSITION_COEF_PTR | 4294900200 | +# | DEEP_RAND_CC_PTR | 4294903000 | +# | FRI_COM_PTR | 4294903200 | +# | MAIN_TRACE_COM_PTR | 4294903300 | +# | AUX_TRACE_COM_PTR | 4294903301 | +# | COMPOSITION_POLY_COM_PTR | 4294903302 | +# | LDE_SIZE_PTR | 4294903303 | +# | Z_PTR | 4294903304 | +# | NUM_QUERIES_PTR | 4294903305 | +# | TRACE_LENGTH_PTR | 4294903306 | +# | TRACE_LENGTH_LOG_PTR | 4294903307 | +# | GRINDING_FACTOR_PTR | 4294903308 | +# | ZERO_WORD_PTR | 4294903309 | +# | ZERO_ZERO_ZERO_FOUR_PTR | 4294903310 | +# | C_PTR | 4294903311 | +# | R1_PTR | 4294903312 | +# | R2_PTR | 4294903313 | +# | TMP1 | 4294903315 | +# | TMP2 | 4294903316 | +# | TMP3 | 4294903317 | +# | TMP4 | 4294903318 | +# | TMP5 | 4294903319 | +# | TMP6 | 4294903320 | +# | TMP7 | 4294903321 | +# | TMP8 | 4294903322 | +# | TMP9 | 4294903323 | +# +------------------------------------------+-------------------------+ + +# ACCESSORS +# ================================================================================================= + +# Procedure to push the trace domain generator address to the stack. +# +# Input: [...] +# Output: [ptr, ...] wher ptr is the memory address of the trace domain generator +# Cycles: 1 +export.trace_domain_generator_ptr + push.TRACE_DOMAIN_GENERATOR_PTR +end + +export.domain_offset + push.DOMAIN_OFFSET +end + +export.num_fri_queries + push.NUM_FRI_QUERIES +end + +export.remainder_codeword_offset + push.REMAINDER_CODEWORD_OFFSET +end + +export.domain_offset_inv + push.DOMAIN_OFFSET_INV +end + +export.trace_domain_generator + push.16777216 +end + +export.lde_domain_generator + push.9113133275150391358 +end + +export.public_inputs_ptr + push.PUBLIC_INPUTS_PTR +end + +export.ood_trace_ptr + push.OOD_TRACE_PTR +end + +export.ood_constraint_evals_ptr + push.OOD_CONSTRAINT_EVALS_PTR +end + +export.current_trace_row_ptr + push.CURRENT_TRACE_ROW_PTR +end + +export.composition_coef_ptr + push.COMPOSITION_COEF_PTR +end + +export.deep_rand_coef_ptr + push.DEEP_RAND_CC_PTR +end + +export.fri_com_ptr + push.FRI_COM_PTR +end + +export.main_trace_com_ptr + push.MAIN_TRACE_COM_PTR +end + +export.composition_poly_com_ptr + push.COMPOSITION_POLY_COM_PTR +end + +#! Address to store details about the lde size. +#! +#! Memory is `[lde_size, log(lde_size), lde_g, 0]` +export.lde_size_ptr + push.LDE_SIZE_PTR +end + +#! Address for the point `z` and its exponentiation `z^N` where `N=trace_len`. +#! +#! Memory is `[(z_1, z_0)^n, z_1, z_0]` +export.z_ptr + push.Z_PTR +end + +export.number_queries_ptr + push.NUM_QUERIES_PTR +end + +export.trace_length_ptr + push.TRACE_LENGTH_PTR +end + +export.trace_length_log_ptr + push.TRACE_LENGTH_LOG_PTR +end + +export.grinding_factor_ptr + push.GRINDING_FACTOR_PTR +end + +export.zero_word + push.ZERO_WORD_PTR +end + +export.zero_zero_zero_four_word + push.ZERO_ZERO_ZERO_FOUR_PTR +end + +#! Returns the pointer to the capacity word of the random coin. +#! +#! Note: The random coin is implemented using a hash function, this returns the +#! capacity portion of the RPO. +export.c_ptr + push.C_PTR +end + +#! Returns the pointer to the first rate word of the random coin. +#! +#! Note: The random coin is implemented using a hash function, this returns the +#! first rate word of the RPO. +export.r1_ptr + push.R1_PTR +end + +#! Returns the pointer to the second rate word of the random coin. +#! +#! Note: The random coin is implemented using a hash function, this returns the +#! second rate word of the RPO. +export.r2_ptr + push.R2_PTR +end + +#! Address to store details to compute deep query denominators. +#! +#! Memory is `[gz1, gz0, z_1, z_0]` +export.tmp1 + push.TMP1 +end + +export.tmp2 + push.TMP2 +end + +export.tmp3 + push.TMP3 +end + +export.tmp4 + push.TMP4 +end + +export.tmp5 + push.TMP5 +end + +export.tmp6 + push.TMP6 +end + +export.tmp7 + push.TMP7 +end + +export.tmp8 + push.TMP8 +end + +export.tmp9 + push.TMP9 +end + +export.tmp10 + push.TMP10 +end + +export.tmp11 + push.TMP11 +end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm b/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm new file mode 100644 index 0000000000..66243ea47f --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm @@ -0,0 +1,573 @@ +use.std::crypto::dsa::rpo_stark::constants + +#! Computes a single step of the random linear combination defining the DEEP composition polynomial +#! that is the input to the FRI protocol. More precisely, the sum in question is: +#! $$ +#! \sum_{i=0}^k{\alpha_i \cdot \left(\frac{T_i(x) - T_i(z)}{x - z} + +#! \frac{T_i(x) - T_i(z \cdot g)}{x - z \cdot g} \right)} +#! $$ +#! +#! and the following instruction computes the denominators $\alpha_i \cdot (T_i(x) - T_i(z))$ and +#! $\alpha_i \cdot (T_i(x) - T_i(z \cdot g))$ and stores the values in two accumulators $r$ and $p$, +#! respectively. This instruction is specialized to auxiliary trace columns i.e. the values $T_i(x)$ +#! are field elements in a quadratic extension field. +#! +#! The stack transition of the instruction can be visualized as follows: +#! +#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+------+------+---+ +#! | T31 | T30 | T21 | T20 | T11 | T10 | T01 | T00 | p1 | p0 | r1 | r0 |x_addr|z_addr|a_addr| - | +#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+------+------+---+ +#! +#! || +#! \/ +#! +#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+--------+--------+-----+ +#! | T31 | T30 | T21 | T20 | T11 | T10 | T01 | T00 | p1' | p0' | r1' | r0' |x_addr|z_addr+1|a_addr+b| - | +#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+--------+--------------+ +#! +#! +#! Here: +#! 1- Tij for i in 0..=3 and j=0,1 stands for the the value of the j-th coordinate in the quadratic extension field +#! of the i-th auxiliary trace polynomial for the current query i.e. $T_i(x)$. +#! 2- (p0, p1) stands for an extension field element accumulating the values for the quotients with common denominator (x - gz). +#! 3- (r0, r1) stands for an extension field element accumulating the values for the quotients with common denominator (x - z). +#! 4- x_addr is the memory address from which we are loading the Ti's using the MSTREAM instruction. +#! 5- z_addr is the memory address to the i-th OOD evaluation frame at z and gz i.e. T_i(z):= (T_i(z)0, T_i(z)1) and T_i(gz):= (T_i(gz)0, T_i(gz)1) +#! 6- a_addr is the memory address of the i-th random element used in batching the trace polynomial quotients. +#! The random elements a := (a0, a1) are stored in memory as [0, 0, a0, a1]. +#! +#! Input: [T31, T30, T21, T20, T11, T10, T01, T00, p1, p0, r1, r0, x_addr, z_addr, a_addr, 0] +#! Output: [T01, T00, T31, T30, T21, T20, T11, T10, p1', p0', r1', r0', x_addr, z_addr', a_addr', 0] +export.combine_aux + + # 1) Shift trace columns values (as quadratic extension field element) left + movup.7 movup.7 + #=> [T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr, a_addr, 0] + + # 2) Get a_addr and update it. This is done here before it becomes inaccessible. + + # Update a_addr + dup.14 add.1 swap.15 + #=> [a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr, a_addr', 0] + + # 3) Load i-th OOD frame portion. This assumes that the OOD frame has been serialized with `current` and `next` rows interleaved. + # This also updates the z_addr pointer. + dup.14 add.1 swap.15 + padw movup.4 mem_loadw + #=> [Tgz1, Tgz0, Tz1, Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + # 4) Compute the numerators + + # a) Compute T_i - T_i(z). This equals, in the case of T0, (T01 - Tz1, T00 - Tz0) + dup.6 dup.6 + movup.5 movup.5 + #=> [Tz1, Tz0, T01, T00, Tgz1, Tgz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + ext2sub + #=> [T01 - Tz1, T00 - Tz0, Tgz1, Tgz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + movdn.3 movdn.3 + #=> [Tgz1, Tgz0, T01 - Tz1, T00 - Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + # b) Compute T_i - T_i(gz). This equals, in the case of T0, (T01 - Tgz1, T00 - Tgz0) + + # Compute first -(T_i - T_i(gz)) + dup.6 dup.6 + ext2sub + #=> [Tgz1 - T01, Tgz0 - T00, T01 - Tz1, T00 - Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + # Negate both coordinates + neg swap neg swap + #=> [T01 - Tgz1, T00 - Tgz0, T01 - Tz1, T00 - Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + #=> [Δg1, Δg0, Δ1, Δ0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + # where Δg1 := T01 - Tgz1, Δg0 := T00 - Tgz0, Δ1 := T01 - Tz1 and Δ0 := T00 - Tz0 + + # 5) Multiply by randomness + + # a) Load randomness from memory + padw + movup.8 mem_loadw drop drop + #=> [a1', a0', a1, a0, Δg1, Δg0, Δ1, Δ0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + # b) Multiply (Δ0, Δ1) + dup.1 dup.1 + movup.7 movup.7 + #=> [Δ1, Δ0, a1, a0, a1, a0, Δg1, Δg0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + ext2mul + #=> [prod1, prod0, a1, a0, Δg1, Δg0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + # where (prod0, prod1) := (Δ0, Δ1) * (a0, a1) + + movdn.5 movdn.5 + #=> [a1, a0, Δg1, Δg0, prod1, prod0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + + # c) Multiply (Δg0, Δg1) + ext2mul + #=> [prodg1, prodg0, prod1, prod0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] + # where (prodg0, prodg1) := (Δg0, Δg1) * (a0, a1) + + # 6) Accumulate into (p0, p1) and (r0, r1) + movupw.3 + + # a) Accumulate into (r0, r1) + movup.7 movup.7 + #=> [prod1, prod0, p1, p0, r1, r0, prodg1, prodg0, T01, T00, T31, T30, T21, T20, T11, T10, x_addr, z_addr', a_addr', 0] + movup.5 movup.5 ext2add + #=> [r1', r0', p1, p0, prodg1, prodg0, T01, T00, T31, T30, T21, T20, T11, T10, x_addr, z_addr', a_addr', 0] + + # b) Accumulate into (p0, p1) + movdn.5 movdn.5 ext2add + #=> [p1', p0', r1', r0', T01, T00, T31, T30, T21, T20, T11, T10, x_addr, z_addr', a_addr', 0] + + # c) Prepare for next iteration + movdnw.2 + #=> [T01, T00, T31, T30, T21, T20, T11, T10, p1', p0', r1', r0', x_addr, z_addr', a_addr', 0] +end + +#! Loads the next query rows in the main, auxiliary and constraint composition polynomials traces. +#! It takes a pointer to the current random query index and returns that index. +#! +#! Input: [query_ptr, ...] +#! Output: [index, query_ptr, ...] +#! +#! Cycles: 131 +proc.load_query_row + # Main trace portion of the query + + ## Get the next query index + dup.4 + mem_loadw + #=> [index, depth, y, y, query_ptr, ...] + + ## Get main trace commitment and use it to get the leaf + movdn.3 movdn.2 + push.0.0 + exec.constants::main_trace_com_ptr mem_loadw + #=>[R, depth, index, query_ptr, ...] + + ## Get the leaf in the main trace commitment and save it + dup.5 dup.5 + mtree_get + exec.constants::tmp3 mem_storew + adv.push_mapval + #=>[V, R, depth, index, query_ptr, ...] + + drop + exec.constants::current_trace_row_ptr + swapw + #=>[R, ptr, y, y, y, depth, index, query_ptr, ...] + exec.constants::zero_zero_zero_four_word mem_loadw + padw + padw + #=> [Y, Y, 0, 0, 0, 4, ptr, y, y, y] + + adv_pipe hperm + ## Store the last full word of main segment columns + adv_loadw + dup.12 mem_storew + swapw + exec.constants::zero_word mem_loadw + dup.12 add.1 mem_storew + #=> [Y, L, Y, ptr, y, y, y, depth, index, query_ptr, ...] + + hperm + + ## Hash with the salt to get the leaf value + exec.constants::zero_word mem_loadw + swapw.2 + + adv_loadw + hperm + + ## Load the leaf value we got using mtree_get + exec.constants::tmp3 mem_loadw + + ## Check correctness of unhashing + movup.4 + assert_eq + movup.3 + assert_eq + movup.2 + assert_eq + assert_eq + #=> [Y, ptr, y, y, y, depth, index, query_ptr, ...] + + ## increment ptr to account for the last two words we saved + swapw add.2 swapw + + # Constraint composition trace part + + ## Load commitment constraint trace and get leaf + exec.constants::composition_poly_com_ptr mem_loadw + dup.9 + dup.9 + mtree_get + + exec.constants::tmp3 mem_storew + adv.push_mapval + #=>[L, R, ptr, y, y, y, depth, index, query_ptr, ...] + padw + # 26 felt + exec.constants::zero_word mem_loadw + drop push.2 swap.3 + swapw.2 + repeat.3 + adv_pipe hperm + end + + # TODO: Optimize by padding the leaf values so that we can use an adv_pipe + dropw adv_push.1 adv_push.1 push.0.0 + dup.12 mem_storew + swapw exec.constants::zero_word mem_loadw + dup.12 add.1 mem_storew + hperm + + ## Hash with the salt to get the leaf value + exec.constants::zero_word mem_loadw + swapw.2 + adv_loadw + hperm + + ## Load the leaf value we got using mtree_get + exec.constants::tmp3 mem_loadw + + ## Check correctness of unhashing + exec.constants::tmp3 mem_loadw + movup.4 + assert_eq + movup.3 + assert_eq + movup.2 + assert_eq + assert_eq + #=> [Y, ptr, y, y, y, depth, index, query_ptr, ...] + + drop + #=> [Y, Y, index, query_ptr, ...] +end + +#! Takes a query index and computes x := offset * domain_gen^index. It also computes the denominators +#! (x - z) and (x - gz). +#! +#! Input: [index, ...] +#! Output: [Z, x, index, ...] where Z := [-gz1, x -gz0, -z1, x - z0] +#! +#! Cycles: 57 +proc.compute_denominators + # Compute x = offset * domain_gen^index + exec.constants::lde_domain_generator dup.1 + exp.u32 + exec.constants::domain_offset mul + #=> [x, index, ...] + + padw + exec.constants::tmp10 mem_loadw + #=> [-z0, -gz0, -gz1, -z1, x, index, ...] + + # Compute Z := [-z1, x - z0, -gz1, x -gz0] + dup.4 add + #=> [x -z0, -gz0, -gz1, -z1, x, index, ...] + movdn.3 + #=> [-gz0, -gz1, -z1, x - z0, x, index, ...] + dup.4 add swap + #=> [-gz1, x -gz0, -z1, x - z0, x, index, ...] +end + +#! Takes a query index and computes x := offset * domain_gen^index. It also computes the denominators +#! (x - z) and (x - gz). +#! +#! Input: [Y, Y, index, ...] +#! Output: [Z, Y, x, index, ...] where Z := [-gz1, x -gz0, -z1, x - z0] +#! +#! Cycles: 57 +proc.compute_denominators_new + exec.constants::tmp10 mem_loadw + #=> [-z0, -gz0, -gz1, -z1, Y, index, ...] + + exec.constants::lde_domain_generator dup.9 + exp.u32 + exec.constants::domain_offset mul + #=> [x, -z0, -gz0, -gz1, -z1, Y, index, ...] + + dup movup.2 add + #=> [x-z0, x, -gz0, -gz1, -z1, Y, index, ...] + movdn.4 + #=> [x, -gz0, -gz1, -z1, x - z0, Y, index, ...] + dup movdn.9 + #=> [x, -gz0, -gz1, -z1, x - z0, Y, x, index, ...] + add swap + #=> [-gz1, x - gz0, -z1, x - z0, Y, x, index, ...] +end + +#! Computes the random linear combination involving the main trace columns and accumulates +#! into an accumulator. +#! More specifically, the procedure takes as input a stack in the following configuration: +#! [Y, Y, Acc, P, ...] where: +#! +#! 1. P := [CURRENT_TRACE_ROW_PTR, OOD_TRACE_PTR, DEEP_RAND_CC_PTR, 0]. +#! 2. [Y, Y] is a "garbage" double-word used to mem_stream data referenced by CURRENT_TRACE_ROW_PTR. +#! 3. Acc =: [Acc3, Acc2, Acc1, Acc0] is the accumulator holding the current numerator values. +#! +#! The procedure then outputs a stack in the same configuration but with the pointers and accumulators +#! updated to [Y`, Y`, Acc`, P`, ...] where: +#! +#! 1. P` := [CURRENT_TRACE_ROW_PTR+18, OOD_TRACE_PTR+70, DEEP_RAND_CC_PTR+70, 0]. +#! 2. [Y`, Y`] is a "garbage" double-word used to later mem_stream auxiliary portion referenced now +#! by CURRENT_TRACE_ROW_PTR`. +#! 3. Acc` is the accumulator holding the updated numerator values i.e. with terms involving main +#! trace columns included. +#! +#! Input: [Y, Y, Acc, P, ...] +#! Output: [Y`, Y`, Acc`, P`, ...] +#! +#! Cycles: 14 +proc.combine_main_trace_columns + mem_stream + repeat.8 + rcomb_base + end + + mem_stream + repeat.4 + rcomb_base + end +end + +#! Computes the random linear combination involving the aux trace columns and accumulates +#! into an accumulator. +#! More specifically, the procedure takes as input a stack in the following configuration: +#! [Y, Y, Acc, P, ...] where: +#! +#! 1. P := [CURRENT_TRACE_ROW_PTR, OOD_TRACE_PTR, DEEP_RAND_CC_PTR, 0]. +#! 2. [Y, Y] is a "garbage" double-word used to mem_stream data referenced by CURRENT_TRACE_ROW_PTR. +#! 3. Acc =: [Acc3, Acc2, Acc1, Acc0] is the accumulator holding the current numerator values. +#! +#! The procedure then outputs a stack in the same configuration but with the pointers and accumulators +#! updated to [Y`, Y`, Acc`, P`, ...] where: +#! +#! 1. P` := [CURRENT_TRACE_ROW_PTR+4, OOD_TRACE_PTR+7, DEEP_RAND_CC_PTR+7, 0]. +#! 2. [Y`, Y`] is a "garbage" double-word used to later mem_stream constraint composition polynomial +#! trace portion referenced now by CURRENT_TRACE_ROW_PTR`. +#! 3. Acc` is the accumulator holding the updated numerator values i.e. with terms involving main +#! trace columns included. +#! +#! Input: [Y, Y, Acc, P, ...] +#! Output: [Y`, Y`, Acc`, P`, ...] +#! +#! Cycles: 9 +proc.combine_aux_trace_columns + # Compute the random linear combination of the first 4 auxiliary trace columns + mem_stream + repeat.4 + exec.combine_aux + end + + # Compute the random linear combination of the last 3 auxiliary trace columns + mem_stream + repeat.3 + exec.combine_aux + end +end + +#! Computes the random linear combination involving the constraint composition polynomial trace +#! columns and accumulates into an accumulator. +#! More specifically, the procedure takes as input a stack in the following configuration: +#! [Y, Y, Acc, P, ...] where: +#! +#! 1. P := [CURRENT_TRACE_ROW_PTR, OOD_TRACE_PTR, DEEP_RAND_CC_PTR, 0]. +#! 2. [Y, Y] is a "garbage" double-word used to mem_stream data referenced by CURRENT_TRACE_ROW_PTR. +#! 3. Acc =: [Acc3, Acc2, Acc1, Acc0] is the accumulator holding the current numerator values. +#! +#! The procedure then outputs the final accumulator value including main and auxiliary trace columns +#! as well as constraint composition polynomial columns. +#! The procedure uses the `combine_aux` by discarding its effect on the second half of the +#! accumulator (i.e. the "gz" part). To do this, we save the value of the accumulator before calling +#! `combine_aux` and then restore the second half of the accumulator after the call. +#! +#! Input: [Y, Y, Acc, P, ...] +#! Output: [Acc`, ...] +#! +#! Cycles: 36 +proc.combine_constraint_poly_columns + # Save Acc + swapw.2 + exec.constants::tmp3 mem_storew + swapw.2 + + # Combine + repeat.3 + mem_stream + repeat.4 + exec.combine_aux + end + end + + # TODO: optimize this so as to keep the randomizer on the stack + mem_stream + dropw + exec.constants::tmp9 mem_storew dropw + #=> [Y, Y, Acc, P, ...] + + + # Restore the correct second half of the accumulator + swapw + exec.constants::tmp3 mem_loadw + #=> [Acc3, Acc2, y, y, y, y, Acc1`, Acc0`, ...] + movdn.5 movdn.5 + #=> [y, y, y, y, Acc3, Acc2, Acc1`, Acc0`, ...] + dropw + #=>[Acc`, ...] +end + +#! Takes the two accumulators holding the numerator values of the two sums and divides them by +#! the denominators and sums them to get the final result. +#! More specifically, the procedure takes as input a stack in the following configuration: +#! [Acc, Z, ...] and computes (a/c) + (b/d) where: +#! 1. a is (Acc0, Acc1) as an element in quadratic extension field. +#! 2. b is (Acc2, Acc3) as an element in quadratic extension field. +#! 3. c is (Z0, Z1) as an element in quadratic extension field. +#! 4. d is (Z2, Z3) as an element in quadratic extension field. +#! +#! Input: [Acc, Z, ...] +#! Ouput: [eval1, eval0, ...] +#! +#! Cycles: 47 +proc.divide_by_denominators_and_sum + ## divide (Acc0, Acc1) by (Z1, Z0) + movup.5 movup.5 ext2div + #=> [Acc3`, Acc2`, Acc1, Acc0, Z1, Z0] + swap.5 movup.4 movup.2 movdn.5 + #=> [Z1, Z0, Acc1, Acc0, Acc3`, Acc2`] + ext2div + #=> [Acc1`, Acc0`, Acc3`, Acc2`] + + ## Sum the two accumulators to get the final result i.e. the query evaluation + ext2add + #=> [eval1, eval0, ...] + + padw exec.constants::tmp9 mem_loadw drop drop + #=> [r1, r0, eval1, eval0, ...] + + ext2add + #=> [eval1, eval0, ...] +end + +#! Compute the DEEP composition polynomial FRI queries. +#! +#! Input: [query_ptr, ...] +#! Output: [...] +#! Cycles: 24 + num_queries * 315 +export.compute_deep_composition_polynomial_queries + exec.constants::fri_com_ptr + dup.1 + push.0 + exec.constants::deep_rand_coef_ptr + exec.constants::ood_trace_ptr + exec.constants::current_trace_row_ptr + exec.constants::tmp11 mem_storew + #=>[X, query_ptr, query_end_ptr, ...] + + # Compute the negations of z and gz. + # We do it here as this computation is common to all queries. + exec.constants::z_ptr mem_loadw + drop drop + neg swap neg + #=> [-z0, -z1, ...] + dup.1 exec.constants::trace_domain_generator mul + #=> [-gz1, -z0, -z1, ...] + swap + #=> [-z0, -gz1, -z1, ...] + dup exec.constants::trace_domain_generator mul + #=> [-gz0, -z0, -gz1, -z1, ...] + swap + #=> [-z0, -gz0, -gz1, -z1, ...] + exec.constants::tmp10 mem_storew + #=>[X, query_ptr, query_end_ptr, ...] + + push.1 + while.true + # I) + # + # Load the (main, aux, constraint)-traces rows associated with the current query and get + # the index of the query. + # + # Cycles: 131 + exec.load_query_row + #=>[Y, Y, index, query_ptr, query_end_ptr, ...] + + # II) + # + # Compute x := offset * domain_gen^index and denominators (x - z) and (x - gz) + # + # Cycles: 57 + exec.compute_denominators_new + #=> [Z, Y, x, index, query_ptr, query_end_ptr, ...] where Z := [-gz1, x - gz0, -z1, x - z0] + + # III) + # + # Prepare to compute the sum \sum_{i=0}^k{\left(\alpha_i \cdot \frac{T_i(x) - T_i(z)}{x - z} + # + \alpha_i \cdot \frac{T_i(x) - T_i(z \cdot g)}{x - z \cdot g} + # We can factorize (x - z) and (x - gz) and divide the two sums only once and at the end. + # The two sums are stored in [Acc3, Acc2] and [Acc1, Acc0] respectively. + + ## a) Push pointers + ## + ## Cycles: 3 + swapw exec.constants::tmp11 mem_loadw + #=> [P, Z, x, index, query_ptr, query_end_ptr, ...] + # where P := [CURRENT_TRACE_ROW_PTR, OOD_TRACE_PTR, DEEP_RAND_CC_PTR, 0] + + ## b) Push the accumulators + ## + ## Cycles: 4 + padw + #=> [Acc, P, Z, x, index, query_ptr, query_end_ptr, ...] + #=> where Acc =: [Acc3, Acc2, Acc1, Acc0] + + ## c) This will be used to mstream the elements T_i(x) + ## + ## Cycles: 8 + padw padw + #=> [Y, Y, Acc, P, Z, x, index, query_ptr, query_end_ptr, ...] + + ## d) Compute the random linear combination + ## + ## Cycles: 14 + 36 = 50 + exec.combine_main_trace_columns + exec.combine_constraint_poly_columns + #=> [Acc, Z, x, index, query_ptr, query_end_ptr, ...] + + ## e) Divide by denominators and sum to get final result + ## + ## Cycles: 47 + exec.divide_by_denominators_and_sum + #=> [eval1, eval0, x, index, query_ptr, query_end_ptr, ...] + + # IV) + # + # Store [poe, index, eval_1, eval_0] where poe := g^index = x / offset and prepare stack + # for next iteration. + + ## a) Compute poe + ## + ## Cycles: 4 + movup.3 movup.3 + exec.constants::domain_offset_inv mul + #=> [poe, index, eval1, eval0, query_ptr, query_end_ptr, ...] + + ## b) Store [eval0, eval1, index, poe] + ## + ## Cycles: 5 + dup.4 add.1 swap.5 + mem_storew + #=> [poe, index, eval1, eval0, query_ptr+1, query_end_ptr, ...] + + ## c) Prepare stack for next iteration + ## + ## Cycles: 4 + dup.5 dup.5 + neq + #=> [?, X, query_ptr+1, query_end_ptr, ...] + end + dropw drop drop +end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/fri.masm b/stdlib/asm/crypto/dsa/rpo_stark/fri.masm new file mode 100644 index 0000000000..254c1df9a3 --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/fri.masm @@ -0,0 +1,221 @@ +use.std::crypto::dsa::rpo_stark::constants + + +#! Checks that, for a query with index p at layer i, the folding procedure to create layer (i + 1) +#! was performed correctly. This also advances layer_ptr by 2 to point to the next query layer. +#! +#! Input: [layer_ptr, layer_ptr, poe, p, e1, e0, layer_ptr, rem_ptr, x, x, x, x, x, x, x, x, ...] +#! Output: [layer_ptr + 2, layer_ptr + 2, poe^4, f_pos, ne1, ne0, layer_ptr + 2, rem_ptr, x, x, x, x, x, x, x, x, ...] +#! +#! Cycles: 81 +export.verify_query_layer.3 + + # load layer commitment C as well as [a0, a1, t_depth, d_size] (7 cycles) + swapdw + movup.8 + add.1 + mem_loadw # load [a0, a1, t_depth, d_size] from layer_ptr + 1 + swapw + movup.8 + mem_loadw # load C from layer_ptr + # => [C, d_size, t_depth, a1, a0, poe, p, e1, e0, layer_ptr, rem_ptr, ...] + + # verify Merkle auth path for (index = f_pos, depth = t_depth, Root = C) (19 cycles) + swapw.2 # [poe, p, e1, e0, d_size, t_depth, a1, a0, C, layer_ptr, rem_ptr, ...] + swap # [p, poe, e1, e0, d_size, t_depth, a1, a0, C, layer_ptr, rem_ptr, ...] + movup.4 # [d_size, p, poe, e1, e0, t_depth, a1, a0, C, layer_ptr, rem_ptr, ...] + u32divmod # p and d_size must be u32 values + movup.5 + movupw.2 + dup.5 + movup.5 # [t_depth, f_pos, C, f_pos, d_seg, poe, e1, e0, a1, a0, layer_ptr, rem_ptr, ...] + mtree_get # [V, C, f_pos, d_seg, poe, e1, e0, a1, a0, layer_ptr, rem_ptr, ...] + + adv.push_mapval + swapw + # => [V, C, f_pos, d_seg, poe, e1, e0, a1, a0, layer_ptr, rem_ptr, ...] + # where f_pos = p % d_size and d_seg = p / 4 + + # unhash V and save the pre-image in locaddr.0 and locaddr.1; we don't clear values of C + # because adv_pipe overwrites the first 8 elements of the stack (15 cycles) + locaddr.1 + movdn.4 + push.0.0.0.0 + swapw + push.0.0.0.0 + adv_pipe + hperm + # => [T2, T1, T0, ptr, V, f_pos, d_seg, poe, e1, e0, a1, a0, layer_ptr, rem_ptr, ..] + + # Hash the digest with the salt + exec.constants::zero_word mem_loadw + swapw.2 + adv_loadw + hperm + + # assert T1 == V (16 cycles) + swapw.3 + drop + movup.3 + assert_eq + movup.2 + assert_eq + assert_eq + movup.9 + assert_eq + + # load (v7, ..v0) from memory (8 cycles) + loc_loadw.1 + swapw + loc_loadw.2 + # => [v7, ..., v0, f_pos, d_seg, poe, e1, e0, a1, a0, layer_ptr, rem_ptr, ...] + + # fold by 4 (1 cycle) + fri_ext2fold4 + # => [x, x, x, x, x, x, x, x, x, x, layer_ptr + 2, poe^4, f_pos, ne1, ne0, rem_ptr, ...] + + # prepare for next iteration (10 cycles) + swapdw + dup.2 + movdn.7 + drop + drop + dup + dup.7 + dup.1 + neq + # => [?, layer_ptr + 2, layer_ptr + 2, poe^4, f_pos, ne1, ne0, layer_ptr + 2, rem_ptr, x, x, x, x, x, x, x, x, ...] +end + +#! Verifies one FRI query. +#! +#! Input: [poe, p, e1, e0, layer_ptr, rem_ptr, ...] +#! Output: [x, x, x, x, x, x, x, x, x, x, ...] +#! +#! - poe is g^p. +#! - p is a query index at the first layer. +#! - (e0, e1) is an extension field element corresponding to the value of the first layer at index p. +#! - layer_ptr is the memory address of the layer data (Merkle tree root, alpha etc.) for the next +#! layer. +#! - rem_ptr is the memory address of the remainder codeword. +#! +#! Cycles: 40 + num_layers * 81 +export.verify_query + + # prepare stack to be in a form that leverages the fri_ext2fold4 instruction output stack state + # (16 cycles) + dup.5 + dup.5 + push.0.0.0.0 + push.0.0.0.0 + swapdw + dup + dup + movup.3 + neq + # => [?, layer_ptr, layer_ptr, poe, p, e1, e0, layer_ptr, rem_ptr, 0, 0, 0, 0, 0, 0, 0, 0, ...] + + # verify correctness of layer folding + while.true + exec.verify_query_layer + end + # => [rem_ptr, rem_ptr, poe^(2^n), f_pos, ne1, ne0, rem_ptr, rem_ptr, x, x, x, x, x, x, x, x, ...] + + # check that remainder[f_pos] == (ne0, ne1) + + # Since each memory address contains two extension field elements, we have to determine which + # of the two elements we should compare against. (7 cycles) + movup.3 + push.2 + u32divmod # f_pos must be a u32 value + movdn.4 + dup.1 + dup.1 + add + # => [rem_ptr + offset, x, x, x, x, ?, ne1, ne0, rem_ptr, rem_ptr, x, x, x, x, x, x, x, x, ..] + + mem_loadw + # => [e1', e0', e1, e0, ?, ne1, ne0, rem_ptr, rem_ptr, x, x, x, x, x, x, x, x, ..] + + # compare (ne0, ne1) to the appropriate tuple from the remainder word (14 cycles) + movup.2 + swap + dup.4 + cdrop + movdn.3 + movup.2 + cdrop + swap.2 + assert_eq + assert_eq + # => [x, x, x, x, x, x, x, x, x, x, ...] +end + +#! Verifies a FRI proof where the proof was generated over the quadratic extension of the base +#! field and layer folding was performed using folding factor 4. +#! Note that the check that the remainder codeword corresponds to the remainder polynomial received +#! by the verifier should now be performed by the calling procedure. +#! +#! Input: [query_ptr, layer_ptr, rem_ptr, g, ...] +#! Output: [...] +#! +#! - query_ptr is a pointer to a list of tuples of the form (e0, e1, p, poe) where poe is equal +#! to g^p with g being the initial FRI domain generator. p is the query index at the first layer +#! and (e0, e1) is an extension field element corresponding to the value of the first layer at index p. +#! - layer_ptr is a pointer to the first layer commitment denoted throughout the code by C. +#! layer_ptr + 1 points to the first [alpha0, alpha1, t_depth, d_size] where d_size is the size +#! of initial domain divided by 4, t_depth is the depth of the Merkle tree commitment to the +#! first layer and (alpha0, alpha1) is the first challenge used in folding the first layer. +#! Both t_depth and d_size are expected to be smaller than 2^32. Otherwise, the result of +#! this procedure is undefined. +#! - rem_ptr is a pointer to the first tuple of two consecutive degree 2 extension field +#! elements making up the remainder codeword. This codeword can be of length either 32 or 64. +#! +#! The memory referenced above is used contiguously, as follows: +#! +#! [query_ptr ... layer_ptr ... rem_ptr ...] +#! +#! This means for example that: +#! 1. rem_ptr - 1 points to the last (alpha0, alpha1, t_depth, d_size) tuple. +#! 2. layer_ptr - 1 points to the last (e0, e1, p, poe) tuple. +#! +#! Cycles: 7 + 4 + num_queries * (40 + num_layers * 81 + 26) +export.verify.1 + + # store [query_ptr, layer_ptr, rem_ptr, g] to keep track of all queries + # (3 cycles) + loc_storew.0 + + # [(query_ptr == layer_ptr), query_ptr, layer_ptr, rem_ptr, g] + # (4 cycles) + dup + dup.2 + neq + + #drop + while.true + # load [e0, e1, p, poe] from memory i.e. next query data (7 cycles) + push.0.0.0.0 + movup.4 + mem_loadw + # => [poe, p, e1, e0, layer_ptr, rem_ptr, g, ...] + + # we now have everything to verify query p + exec.verify_query + + # prepare for next iteration (18 cycles) + # => [x, x, x, x, x, x, x, x, x, x, g, ...] + dropw drop drop drop + loc_loadw.0 # load [query_ptr, layer_ptr, rem_ptr, g] + add.1 + loc_storew.0 # store [query_ptr + 1, layer_ptr, rem_ptr, g] + dup + dup.2 + neq + #=> [?, query_ptr + 1, layer_ptr, rem_ptr, g, ...] + end + #=> [X, ..] + + dropw +end + \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm b/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm new file mode 100644 index 0000000000..b042b73cff --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm @@ -0,0 +1,202 @@ +use.std::crypto::dsa::rpo_stark::constants +use.std::crypto::hashes::rpo + + +#! Loads OOD evaluation frame, with current and next rows interleaved, into memory. This ouputs +#! the hash of the OOD for reseeding the random coin. +#! +#! Input: [...] +#! Output: [OOD_FRAME_HASH, ...] +#! Cycles: 36 +export.load_evaluation_frame + # We have 12 main trace columns for a total of 24 base field elements per row. + # Since we have two rows, i.e. current and next, the total number of field elements + # making up the OOD evaluation frame is 48. + # The elements are stored from the stack as (a1_1, a1_0, a0_1, a0_0) where a0 is from the + # current row and a1 from the next row. + + exec.constants::ood_trace_ptr + push.0.0.0.0 + padw padw + repeat.6 + adv_pipe + hperm + end + + dropw + swapw + dropw + movup.4 + drop +end + +#! Loads OOD constraint composition polynomial evaluation columns into memory and reseeds the random +#! coin. +#! +#! Input: [...] +#! Output: [EVAL_HASH, ...] +#! Cycles: 160 +export.load_constraint_evaluations + # Read OOD constraint evaluations. These are 8 ExtFelt `value_i` such that the value of the + # constraint evaluation polynomial at `z` `H(z)` equals `\sum_0^7 z^(N * i) value_i` where N + # is the execution trace length. + # In order to facilitate the computation of the DEEP composition polynomial queries, we lay out + # the values in memory as [v0, v1, 0, 0] where v := (v0, v1) ranges over the 8 values `value_i`. + + # Load value_0 and value_1 + padw + padw + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr mem_storew + dropw + + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.1 + mem_storew + + # Load value_2 and value_3 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.2 + mem_storew + dropw + + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.3 + mem_storew + + dropw + hperm + + # Load value_4 and value_5 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.4 + mem_storew + dropw + + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.5 + mem_storew + dropw + + swapw + + # Load value_6 and value_7 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.6 + mem_storew + dropw + + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.7 + mem_storew + dropw + + hperm + + # Load value_8 and value_9 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.8 + mem_storew + dropw + + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.9 + mem_storew + dropw + + swapw + + # Load value_10 and value_11 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.10 + mem_storew + dropw + + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.11 + mem_storew + dropw + + hperm + + exec.rpo::squeeze_digest +end + +#! Computes the H(z) evaluation of the constraint composition polynomial at the OOD element z. +#! +#! Input: [...] +#! Output: [res1, res0, ...] +#! Cycles: 155 +export.compute_Hz + # Load the pointer to the OOD constraint polynomials evaluations + exec.constants::ood_constraint_evals_ptr + # => [ptr, ...] + + # Compute `H(z)` + ## Load `value_i`'s + + # Load value_0 + padw dup.4 mem_loadw + # => [0, 0, v0_1, v0_0, ptr, ...] + + # Load value_1 + push.0.0 dup.6 add.1 mem_loadw + # => [0, 0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_2 + push.0.0 dup.8 add.2 mem_loadw + # => [0, 0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_3 + push.0.0 dup.10 add.3 mem_loadw + # => [0, 0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_4 + push.0.0 dup.12 add.4 mem_loadw + # => [0, 0, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_5 + push.0.0 movup.14 movdn.4 dup.4 add.5 mem_loadw + # => [0, 0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_6 + push.0.0 dup.6 add.6 mem_loadw + # => [0, 0, v6_1, v6_0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + # Load value_7 + push.0.0 movup.8 add.7 mem_loadw + # => [0, 0, v7_1, v7_0, v6_1, v6_0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + + ## Load z^N where N is the length of the execution trace + push.0.0 + exec.constants::z_ptr mem_loadw + movup.2 drop + movup.2 drop + # => [z1, z0, value_7, ... ,value_0] + + # Horner evaluation + # TODO: maybe can be done faster in another way + repeat.6 + dup + movdn.6 + dup.1 + movdn.7 + # => [z1, z0, value_7, value_6, z1, z0, value_5, ... ,value_0] + + ext2mul + ext2add + # => [acc1, acc0, z1, z0, value_5, ... ,value_0] + + movup.3 + movup.3 + # => [z1, z0, acc1, acc0, value_5, ... ,value_0] + end + ext2mul + ext2add +end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm b/stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm new file mode 100644 index 0000000000..6cb497ceb7 --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm @@ -0,0 +1,36 @@ +use.std::crypto::dsa::rpo_stark::constants + + +#! Load the public inputs in memory starting from the address referenced by `public_inputs_ptr`. +#! In parallel, compute the hash of the public inputs being loaded. The hashing starts with +#! capacity registers of the hash function set to `C` resulting from hashing the proof context. +#! The ouptut D is the digest of the hashing. +#! +#! Input: [public_inputs_ptr, C] +#! Output: [D] +#! Cycles: 38 +export.load + + # TODO: load the public inputs using public_inputs_ptr + drop + + # Unhash the public inputs from the advice provider. + # The following assumes that the public inputs contain only the input and output states + # of the operand stack and both are of length exactly 16. + # TODO: generalize to any number of public inputs supported by the VM. + padw padw + repeat.4 + adv_loadw + swapw + adv_loadw + hperm + end + adv_loadw + swapw + exec.constants::zero_word mem_loadw + hperm + + dropw + swapw + dropw +end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm new file mode 100644 index 0000000000..2ba509d0e3 --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm @@ -0,0 +1,775 @@ +use.std::crypto::dsa::rpo_stark::constants +use.std::crypto::dsa::rpo_stark::utils +use.std::crypto::hashes::rpo + + +#! Helper procedure to compute addition of two words component-wise. +#! Input: [b3, b2, b1, b0, a3, a2, a1, a0] +#! Output: [c3, c2, c1, c0] +#! +#! Cycles: 16 +proc.add_two_words + movup.3 + movup.7 + add + #=> [c0, b3, b2, b1, a3, a2, a1] + + movup.3 + movup.6 + add + #=> [c1, c0, b3, b2, a3, a2] + + movup.3 + movup.5 + add + #=> [c2, c1, c0, b3, a3] + + movup.3 + movup.4 + add + #=> [c3, c2, c1, c0] +end + +#! Return the first half of the rate portion of the random coin state +#! +#! The random coin uses RPO to generate data. The RPO state is composed of 3 +#! words, 2 words for the rate, and 1 word for the capacity. This procedure +#! returns the first word of the RPO state. +#! +#! Input: [...] +#! Output: [R1, ...] +#! Cycles: 6 +export.get_rate_1 + padw exec.constants::r1_ptr mem_loadw +end + +#! Return the second half of the rate portion of the random coin state +#! +#! The random coin uses RPO to generate data. The RPO state is composed of 3 +#! words, 2 words for the rate, and 1 word for the capacity. This procedure +#! returns the first word of the RPO state. +#! +#! Input: [...] +#! Output: [R2, ...] +#! Cycles: 6 +export.get_rate_2 + padw exec.constants::r2_ptr mem_loadw +end + +#! Return the capacity portion of the random coin state +#! +#! The random coin uses RPO to generate data. The RPO state is composed of 3 +#! words, 2 words for the rate, and 1 word for the capacity. This procedure +#! returns the first word of the RPO state. +#! +#! Input: [...] +#! Output: [C, ...] +#! Cycles: 6 +export.get_capacity + padw exec.constants::c_ptr mem_loadw +end + +#! Initializes the seed for randomness generation by computing the hash of the proof context using +#! the trace length, number of queries, logarithm of blowup factor and the number of bits of +#! grinding. Currently, this part, as well as the rest of the STARK verifier assumes a blowup factor +#! equal to 8. +#! The ouput of this procedure is the capacity portion of the state after applying `hperm`. +#! +#! Input: [ptr, M, PK, ...] +#! Output: [C] +#! Cycles: 55 +export.init_seed.2 + + # Move the pointer behind the public inputs + dup movdn.9 + + # Store the message and public key as public inputs + mem_storew + swapw + dup.8 add.1 + mem_storew + swapw + + # Lay out the proof context + push.3072 + movdn.4 + push.8 + movdn.4 + push.1 + push.4294967295 + + # Hash the proof context, with the message as meta data + # The reason for this hack is the need to have message as a public + # input while not appearing in the main trace. Hence we use the meta + # data field as workaround. + push.4.0.0.0 + exec.constants::zero_zero_zero_four_word mem_storew + movdnw.2 + + hperm + dropw dropw + + #push.132127 + push.132103 + push.0 + push.8 + + # Number of FRI queries + push.100 + #push.122 + + movupw.2 + + hperm + dropw + + # Absorb + movup.8 + mem_loadw + padw + hperm + + dropw + swapw + dropw + # => [C] +end + +#! Reseed the random coin with `DATA` +#! +#! Input: [DATA, ...] +#! Ouput: [...] +#! Cycles: 54 +export.reseed + # Load previous state and update it + # -------------------------------------------------------------------------------------------- + exec.get_rate_1 + # => [R1, DATA, ...] (6 cycles) + + exec.add_two_words + # => [R1, ...] (16 cycles) + + exec.get_capacity + swapw + exec.get_rate_2 + # => [R2, R1, C, ...] (13 cycles) + + hperm + # => [R2', R1', C', ...] (1 cycles) + + # Save the new state to memory + # -------------------------------------------------------------------------------------------- + exec.constants::r2_ptr mem_storew + dropw + exec.constants::r1_ptr mem_storew + dropw + exec.constants::c_ptr mem_storew + dropw + # => [...] (18 cycles) +end + +#! Reseed the random coin with `DATA` +#! +#! Input: [DATA, ...] +#! Ouput: [...] +#! Cycles: 71 +export.reseed_with_salt + # Load previous state and update it + # -------------------------------------------------------------------------------------------- + exec.get_rate_1 + # => [R1, DATA, ...] (6 cycles) + + exec.add_two_words + # => [R1, ...] (16 cycles) + + exec.get_capacity + swapw + exec.get_rate_2 + padw adv_loadw + exec.add_two_words + # => [R2, R1, C, ...] (30 cycles) + + hperm + # => [R2', R1', C', ...] (1 cycles) + + # Save the new state to memory + # -------------------------------------------------------------------------------------------- + exec.constants::r2_ptr mem_storew + dropw + exec.constants::r1_ptr mem_storew + dropw + exec.constants::c_ptr mem_storew + dropw + # => [...] (18 cycles) +end + + +#! Draw constraint composition random coefficients and save them into memory in the region from +#! `compos_coef_ptr` `compos_coef_ptr + 112 - 1` as `(r1_1, r1_0, r0_1, r0_0)` +#! +#! Input: [compos_coef_ptr, ...] +#! Output: [...] +#! Cycles: 203 +export.generate_constraint_composition_coefficients + push.24 + swap + exec.generate_random_coefficients + #=> [...] +end + + +#! Draw deep composition polynomial random coefficients and save them into memory in the region from +#! `deep_rand_coef_ptr` to `deep_rand_coef_ptr + 89 - 1` as `(0, 0, r0_1, r0_0)` +#! The number of coefficients is equal to: +#! 1. 12 * 2 Felt for the main and auxiliary traces. +#! 2. 12 * 2 Felt for constraint polynomial. +#! Total: 24 tuples of type (Felt, Felt) +#! +#! Input: [deep_rand_coef_ptr, ...] +#! Output: [...] +#! Cycles: 520 +export.generate_deep_composition_random_coefficients + push.24 + swap + exec.generate_random_coefficients_pad + #=> [...] +end + + +# COEFFICIENT GENERATION +# ============================================================================================= + +#! Generates a `num_tuples` tuples of random field elements and stores them in memory +#! starting from address `dest_ptr`. Each memory address holds two tuples. +#! TODO: Generalize by keeping track of something similar to the `output` variable in `RpoRandomCoin` +#! so that we keep track of already used randomness and know when there is a need to apply `hperm`. +#! +#! Input: [dest_ptr, num_tuples, ...] +#! Output: [...] +#! +#! Cycles: 69 + (22 * num_tuples) / 4 +proc.generate_random_coefficients + + # Compute the loop counter. We use checked division to make sure the number is a multiple of 4. + # If we use field division and num_tuples is not a multiple of 4 then we will enter into + # a very large loop with high probability. + push.0 dup movup.2 movup.3 + u32assert u32divmod.4 + assertz + neg + #=> [loop_ctr, dest_ptr, x, x, ...] + # where loop_ctr = - num_tuples / 4; we negate the counter so that we can count up to 0 + + exec.get_rate_1 + dup.5 mem_storew + + exec.get_rate_2 + dup.9 add.1 mem_storew + #=> [R2, R1, loop_ctr, dest_ptr, 0, 0, ..] + + exec.get_capacity + swapdw + swapw + swap add.2 swap + #=> [loop_ctr, dest_ptr, 0, 0, R1, C, R2, ..] + + add.1 dup neq.0 + + while.true + + swapw.3 hperm + #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] + + # save R2 to mem[dest+1]; we use dup.13 here because it takes only 1 cycle + dup.13 add.1 mem_storew + #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] + + # save R1 to mem[dest] + swapw dup.13 mem_storew swapw + #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] + + # update destination pointer and loop counter + swapw.3 + #=> [loop_ctr, dest_ptr, x, x, R1, C, R2, ...] + + swap add.2 swap + #=> [loop_ctr, dest_ptr+2, x, x, R1, C, R2, ...] + + add.1 dup + #=> [loop_ctr+1, loop_ctr+1, dest_ptr+2, x, x, R1, C, R2, ...] + + neq.0 + end + + # Save the new state of the random coin + dropw + exec.constants::r1_ptr mem_storew + dropw + exec.constants::c_ptr mem_storew + dropw + exec.constants::r2_ptr mem_storew + dropw + #=> [...] +end + + +#! Generates a `num_tuples` tuples of random field elements and stores them in memory +#! starting from address `dest_ptr`. Each memory address holds one tuple. +#! TODO: Generalize by keeping track of something similar to the `output` variable in `RpoRandomCoin` +#! so that we keep track of already used randomness and know when there is a need to apply `hperm`. +#! +#! Input: [dest_ptr, num_tuples, ...] +#! Output: [...] +#! +#! Cycles: 104 + (69 * num_tuples) / 4 +proc.generate_random_coefficients_pad + + # Compute the loop counter. We use checked division to make sure the number is a multiple of 4. + # If we use field division and num_tuples is not a multiple of 4 then we will enter into + # a very large loop with high probability. + push.0 dup movup.2 movup.3 + u32assert u32divmod.4 + assertz + neg + #=> [loop_ctr, dest_ptr, x, x, ...] + # where loop_ctr = - num_tuples / 4; we negate the counter so that we can count up to 0 + + exec.get_rate_1 + dup.5 + #=> [dest_ptr, a11, a10, a01, a00, loop_ctr, dest_ptr, x, x, ...] + dup.4 + dup.4 + push.0.0 + dup.4 + mem_storew + #=> [0, 0, a01, a00, dest_ptr, a11, a10, a01, a00, loop_ctr, dest_ptr, x, x, ...] + + dropw + dup.2 dup.2 push.0.0 + movup.4 add.1 mem_storew + #=> [0, 0, a11, a10, a11, a10, a01, a00, loop_ctr, dest_ptr, x, x, ...] + + exec.constants::r2_ptr mem_loadw + dup.9 add.4 swap.10 + #=> [dest_ptr, a31, a30, a21, a20, a11, a10, a01, a00, loop_ctr, dest_ptr+4, x, x, ...] + + dup.4 + dup.4 + push.0.0 + dup.4 add.2 + mem_storew + #=> [0, 0, a21, a20, dest_ptr, a31, a30, a21, a20, a11, a10, a01, a00, loop_ctr, dest_ptr+4, x, x, ...] + dropw + dup.2 dup.2 push.0.0 + movup.4 add.3 mem_storew + #=> [0, 0, a31, a30, a31, a30, a21, a20, a11, a10, a01, a00, loop_ctr, dest_ptr+4, x, x, ...] + + exec.constants::c_ptr mem_loadw + swapdw + swapw + #=> [loop_ctr, dest_ptr, 0, 0, R1, C, R2, ..] + + add.1 dup neq.0 + + while.true + + swapw.3 hperm + #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] + + # save R2 to mem[dest+1]; we use dup.13 here because it takes only 1 cycle + dup.13 + dup.4 dup.4 push.0.0 + dup.4 add.2 + mem_storew + #=> [0, 0, a21, a20, dest_ptr, a31, a30, a21, a20, a11, a10, a01, a00, C, loop_ctr, dest_ptr, x, x, ...] + dropw + dup.2 dup.2 push.0.0 + movup.4 add.3 mem_storew + #=> [0, 0, a31, a30, a31, a30, a21, a20, a11, a10, a01, a00, C, loop_ctr, dest_ptr, x, x, ...] + + # save R1 to mem[dest] + dropw + swapw dup.13 + dup.4 dup.4 push.0.0 + dup.4 + mem_storew + #=> [0, 0, a01, a00, dest_ptr, a11, a10, a01, a00, a31, a30, a21, a20, C, loop_ctr, dest_ptr, x, x, ...] + dropw + dup.2 dup.2 push.0.0 + movup.4 add.1 mem_storew + #=> [0, 0, a01, a00, a11, a10, a01, a00, a31, a30, a21, a20, C, loop_ctr, dest_ptr, x, x, ...] + + # reshuffle and update destination pointer and loop counter + dropw + swapw + swapw.3 + #=> [loop_ctr, dest_ptr, x, x, R1, C, R2, ...] + + swap add.4 swap + #=> [loop_ctr, dest_ptr+2, x, x, R1, C, R2, ...] + + add.1 dup + #=> [loop_ctr+1, loop_ctr+1, dest_ptr+2, x, x, R1, C, R2, ...] + + neq.0 + end + + # Save the new state of the random coin + dropw + exec.constants::r1_ptr mem_storew + dropw + exec.constants::c_ptr mem_storew + dropw + exec.constants::r2_ptr mem_storew + dropw + #=> [...] +end + + + +# OOD POINT GENERATION +# ============================================================================================= + +#! Generate the OOD challenge point `z = (z0, z1)` and compute `z^N` where N is +#! the trace length. The resulting word `[(z_1, z_0)^N, z1, z0]` is stored in the +#! global memory address `exec.z_ptr` reservedfor it. +#! +#! Input: [X, ...] +#! Output: [...] +#! Note: The top word on the stack is consumed by this procedure. +#! Cycles: 21 + 10 * log(N) +export.generate_z_zN + # Load z (first two felts of the random coin state) and log trace length N + exec.constants::r1_ptr mem_loadw + drop drop + push.8 + # => [log(trace_len), z_1, z_0, ...] + + dup.2 dup.2 + # => [z_1, z_0, log(trace_len), z_1, z_0, ...] + + # TODO: Fix this part + # Compute z^N using the fact that z^N = z^(2^log(N)) + # Loop starts with `i=log(trace_len)` + push.1 + while.true + dup.1 dup.1 ext2mul + # => [(z_1, z_0)^n, i, z_1, z_0, ...] + + dup.2 sub.1 swap.3 push.1 neq + # => [b, (z_1, z_0)^n, i-1, z_1, z_0, ...] + end + + movup.2 drop + # => [(z_1, z_0)^n, z_1, z_0, ...] + + # Store z and z^N + exec.constants::z_ptr mem_storew + dropw +end + + + +# INDEX GENERATION +# ============================================================================================= + +# Helper function for generating a list of indices that takes a word of random felts and saves +# to memory region referenced by `ptr` 4 random integers in the range 0..=(mask+1). +# `depth` is saved next to each of the 4 integers for use in subsequent steps. +# +# Input: [R, ptr, mask, depth, ...] +# Output:[...] +# +# Cycles: 100 +proc.generate_four_integers + # Get the first random felt + dup.3 # [r0, R1, ptr, mask, depth, ...] + u32split swap # [r0_lo, r0_hi, R1, ptr, mask, depth, ...] + dup.7 # [mask, r0_lo, r0_hi, R1, ptr, mask, depth, ...] + u32and # [r, r0_hi, R1, ptr, mask, depth, ...] + dup.8 swap # [r, depth, r0_hi, R1, ptr, mask, depth, ...] + push.0 movdn.3 # [r, depth, r0_hi, 0, R1, ptr, mask, depth, ...] + + # Store and update pointer + dup.8 add.1 swap.9 # [ptr, r, depth, r0_hi, 0, R1, ptr + 1, mask, depth, ...] + mem_storew + dropw # [R1, ptr + 1, mask, depth, ...] + + # Get the second random felt + dup.2 # [r1, R1, ptr, mask, depth, ...] + u32split swap # [r1_lo, r1_hi, R1, ptr, mask, depth, ...] + dup.7 # [mask, r1_lo, r1_hi, R1, ptr, mask, depth, ...] + u32and # [r, r1_hi, R1, ptr, mask, depth, ...] + dup.8 swap # [r, depth, r1_hi, R1, ptr, mask, depth, ...] + push.0 movdn.3 # [r, depth, r1_hi, 0, R1, ptr, mask, depth, ...] + + # Store and update pointer + dup.8 add.1 swap.9 # [ptr, r, depth, r1_hi, 0, R1, ptr + 1, mask, depth, ...] + mem_storew + dropw # [R1, ptr + 1, mask, depth, ...] + + # Get the third random felt + dup.1 + u32split swap + dup.7 + u32and + dup.8 swap + push.0 movdn.3 + + # Store and update pointer + dup.8 add.1 swap.9 + mem_storew + dropw + + # Get the fourth random felt + dup + u32split swap + dup.7 + u32and + dup.8 swap + push.0 movdn.3 + + # Store and update pointer + dup.8 add.1 swap.9 + mem_storew + dropw +end + +# Helper function for generating a list of indices. It takes a word of random felts and saves +# to a memory region, referenced by `ptr`, 3 random integers in the range 0..=(mask+1). This procedure +# is used to generate a list of random indices that are used in FRI. Moreover, this procedure +# is called first, and right after the PoW check, thus the first element in the rate portion of +# the state is discarded. +# `depth` is saved next to each of the 3 integers for use in subsequent steps. +# +# Input: [R, ptr, mask, depth, ...] +# Output:[R, ptr + 3, mask, depth, ...] +# +# Cycles: 75 +proc.generate_three_integers + # Get the second random felt + dup.2 # [r0, R1, ptr, mask, depth, ...] + u32split swap # [r0_lo, r0_hi, R1, ptr, mask, depth, ...] + dup.7 # [mask, r0_lo, r0_hi, R1, ptr, mask, depth, ...] + u32and # [r, r0_hi, R1, ptr, mask, depth, ...] + dup.8 swap # [r, depth, r0_hi, R1, ptr, mask, depth, ...] + push.0 movdn.3 # [r, depth, r0_hi, 0, R1, ptr, mask, depth, ...] + + # Store and update pointer + dup.8 add.1 swap.9 # [ptr, r, depth, r0_hi, 0, R1, ptr + 1, mask, depth, ...] + mem_storew + dropw # [R1, ptr + 1, mask, depth, ...] + + # Get the second random felt + dup.1 # [r1, R1, ptr, mask, depth, ...] + u32split swap # [r1_lo, r1_hi, R1, ptr, mask, depth, ...] + dup.7 # [mask, r1_lo, r1_hi, R1, ptr, mask, depth, ...] + u32and # [r, r1_hi, R1, ptr, mask, depth, ...] + dup.8 swap # [r, depth, r1_hi, R1, ptr, mask, depth, ...] + push.0 movdn.3 # [r, depth, r1_hi, 0, R1, ptr, mask, depth, ...] + + # Store and update pointer + dup.8 add.1 swap.9 # [ptr, r, depth, r1_hi, 0, R1, ptr + 1, mask, depth, ...] + mem_storew + dropw # [R1, ptr + 1, mask, depth, ...] + + # Get the third random felt + dup.0 + u32split swap + dup.7 + u32and + dup.8 swap + push.0 movdn.3 + + # Store and update pointer + dup.8 add.1 swap.9 + mem_storew + dropw +end + +#! Generate a list of `num_queries` number of random indices in the range +#! [0, lde_size] and store it in memory starting from `query_ptr`. +#! The list is stored as `(r, depth, y, y)` where `depth` is `log(lde_domain_size)`. +#!`depth` is needed when computing the deep queries. +#! TODO: the case of duplicate queries +#! +#! Input: [query_ptr, num_queries, ...] +#! Output: [...] +#! +#! Cycles: 282 + q * 250 + r * 29 where q = num_queries / 8 and r = num_queries % 8 +#! +#! NOTE: This procedure is called first, and right after the PoW check, thus the first element +#! in the rate portion of the state is discarded. +#! NOTE: The cycle count can be estimated, using the fact that r < 8, via the more compact formula +#! 485 + 31 * num_queries +export.generate_list_indices + # push the depth + push.11 + # push the mask + push.2047 + #=> [mask, depth, query_ptr, num_queries] where depth = log(lde_size) + + # Get address holding the integers (this will later hold the FRI queries) + movup.2 + #=> [query_ptr, mask, depth, num_queries] + + # Load the first half of the rate portion of the state of the random coin. We discard the first + # element as it is used for PoW and use the remaining the 3. + exec.get_rate_1 + exec.generate_three_integers + #=> [R, query_ptr, mask, depth, num_queries] + + # Load the second half of the rate portion of the state of the random coin. + exec.constants::r2_ptr mem_loadw + exec.generate_four_integers + #=> [R2, query_ptr, mask, depth, num_queries, ...] + + # Squeeze + exec.constants::c_ptr mem_loadw + exec.get_rate_1 + exec.get_rate_2 + hperm + + # Save the new state + exec.constants::r2_ptr mem_storew + dropw + # => [R1, C] + exec.constants::r1_ptr mem_storew + swapw + # => [C, R1] + exec.constants::c_ptr mem_storew + dropw + #=> [R1, query_ptr, mask, depth, num_queries, ...] + + + # Use `num_queries` to iterate. + + ## Subtract the 7 elements we have already generated above. + movup.7 + push.7 sub + + ## Divide by 8 to get the number of iterations + u32assert u32divmod.8 + #=> [remainder, quotient, X, query_ptr, mask, depth, ...] + + + ## Save remainder for later use + movdn.8 + #=> [quotient, X, query_ptr, mask, depth, remainder, ...] + + ## Use `quotient` to iterate + #add.1 + dup movdn.8 + #push.777 movdn.8 + #=> [quotient, X, query_ptr, mask, depth, quotient, remainder, ...] + + push.0 neq + while.true + exec.generate_four_integers + exec.constants::r2_ptr mem_loadw + exec.generate_four_integers + #=> [R2, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] + + # Squeeze + exec.constants::c_ptr mem_loadw + exec.get_rate_1 + exec.get_rate_2 + hperm + + # Save the new state + exec.constants::r2_ptr mem_storew + dropw + # => [R1, C] + exec.constants::r1_ptr mem_storew + swapw + # => [C, R1] + exec.constants::c_ptr mem_storew + dropw + #=> [R1, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] + + movup.7 sub.1 dup movdn.8 + push.0 neq + end + #=> [R1, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] + + ## Use remainder + + ### Put the remaining number of queries to generate in the appropriate stack position + movup.8 movdn.7 + + ### Load the second half of the rate portion of the state of the random coin. + padw exec.constants::r2_ptr mem_loadw + #=> [R2, R1, query_ptr, mask, depth, num_queries, ...] + + ### Iterate over remainder + dup.11 sub.1 swap.12 + neq.0 + while.true + movup.7 + u32split swap # [r0_lo, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] + dup.10 # [mask, r0_lo, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] + u32and # [r, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] + dup.11 swap # [r, depth, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] + push.0 movdn.3 # [r, depth, r0_hi, 0, R2, r3, r2, r1, ptr, mask, depth, ...] + + # Store and update pointer + dup.11 add.1 swap.12 # [ptr, r, depth, r0_hi, 0, R2, r3, r2, r1, ptr + 1, mask, depth, ...] + mem_storew + drop drop drop # [x, R2, r3, r2, r1, ptr + 1, mask, depth, ...] + dup.11 sub.1 swap.12 + push.0 neq + end + + dropw dropw dropw drop +end + +# PROOF-OF-WORK CHECK +# ============================================================================================= + +#! Check that the Proof-of-Work contained in the nonce is equal to the required number +#! of bits prescribed by grinding bits. The grinding factor is assumed to be less than 32. +#! +#! Input: [grinding_factor, ...] +#! Output: [...] +#! Cycles: 73 +export.check_pow + # Compute the mask. + pow2 + u32assert u32overflowing_sub.1 assertz + #=> [mask, ...] + + # Load Capacity portion + exec.get_capacity + + # Load first half of rate portion and add pow witness to first element of rate + exec.get_rate_1 + adv_push.1 + dup.4 + add + swap.4 + drop + + # Load the second half of rate portion and apply the permutation + padw + exec.constants::r2_ptr mem_loadw + hperm + #=> [R2, R1, C, mask, ...] + + # Save the new random coin state + exec.constants::r2_ptr mem_storew + dropw + exec.constants::r1_ptr mem_storew + swapw + exec.constants::c_ptr mem_storew + dropw + drop drop drop + #=> [R10, mask] + + # Make sure the PoW is valid + u32split + drop + u32and + assertz + drop + #=> [...] +end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/utils.masm b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm new file mode 100644 index 0000000000..bc49309d58 --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm @@ -0,0 +1,148 @@ +use.std::crypto::dsa::rpo_stark::constants +use.std::crypto::dsa::rpo_stark::random_coin +use.std::crypto::fri::ext2fri + +#! Get FRI layer commitments and reseed with them in order to draw folding challenges i.e. alphas. +#! +#! Input: [...] +#! Output: [...] +#! Cycles: 21 + 83 * num_fri_layers +export.load_fri_layer_commitments + # Load the first FRI layer commitment + padw adv_loadw + exec.constants::fri_com_ptr + mem_storew + + + # Reseed + exec.random_coin::reseed_with_salt + # => [...] + + # Squeeze folding randomness alpha + exec.random_coin::get_rate_1 + drop drop + + # Append the LDE size and log size and store + push.9 + push.512 + exec.constants::fri_com_ptr add.1 + mem_storew + + + # Load the second FRI layer commitment + adv_loadw + exec.constants::fri_com_ptr add.2 + mem_storew + + # Reseed + exec.random_coin::reseed_with_salt + # => [...] + + # Squeeze folding randomness alpha + exec.random_coin::get_rate_1 + drop drop + + # Append the LDE size and log size and store + push.7 + push.128 + exec.constants::fri_com_ptr add.3 + mem_storew + + + # Load the third FRI layer commitment + adv_loadw + exec.constants::fri_com_ptr add.4 + mem_storew + + # Reseed + exec.random_coin::reseed_with_salt + # => [...] + + # Squeeze folding randomness alpha + exec.random_coin::get_rate_1 + drop drop + + # Append the LDE size and log size and store + push.5 + push.32 + exec.constants::fri_com_ptr add.5 + mem_storew + + # Clean up the stack + dropw +end + +#! Load the remainder polynomial from the advice provider and check that its hash corresponds +#! to its commitment and reseed with the latter. +#! Load the remainder code word, i.e. the NTT of the remainder polynomial, and use its hash, together, +#! with the hash of the remainder polynomial in order to generate the Fiat-Shamir challenge `tau` for +#! the `verify_remainder_32` procedure. +#! +#! Input: [...] +#! Output: [...] +#! Cycles: 1633 +export.load_and_verify_remainder + # Load remainder commitment and save it at `TMP7` + padw + adv_loadw + exec.constants::tmp7 mem_storew + + # Reseed with remainder commitment + exec.random_coin::reseed_with_salt + + # Capacity portion of the state + padw + + # Load the first 2 coefficients + padw + adv_loadw + + # The FRI layer commitments are stored at addresses ptr, ptr + 2, ptr + 4. The remainder will + # be stored in the region ptr + 6 to ptr + 6 + 16 - 1. Thus the remainder polynomial coefficients + # will be in the region ptr + 22 to ptr + 22 + 2 - 1 + exec.constants::fri_com_ptr add.22 mem_storew + + # Load the last 2 coefficients + padw + adv_loadw + exec.constants::fri_com_ptr add.23 mem_storew + + # Hash the remainder polynomial + hperm + + # Compare Remainder_poly_com with the read commitment + exec.constants::tmp7 mem_loadw + movup.4 + assert_eq + movup.3 + assert_eq + movup.2 + assert_eq + assert_eq + # => [...] + + # Load and hash the remainder codeword + exec.constants::fri_com_ptr exec.constants::remainder_codeword_offset add movdn.4 + padw padw + repeat.8 + adv_pipe hperm + end + # => [Y, R, Y] where R = [y, y, tau1, tau0] + + # Extract the challenge for the probabilistic check + dropw + swapw + dropw + drop + drop + #=> [tau1, tau0] where tau is the challenge of ext2fri::verify_remainder_32 + + # Call the probabilistic check + exec.constants::fri_com_ptr exec.constants::remainder_codeword_offset add + movdn.2 + # => [tau1, tau0, ptr_remainder, ... ] + exec.ext2fri::verify_remainder_32 + # Drop pointer + drop + #=> [...] +end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm new file mode 100644 index 0000000000..73d24eb47c --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm @@ -0,0 +1,187 @@ +use.std::crypto::dsa::rpo_stark::constants +use.std::crypto::dsa::rpo_stark::ood_frames +use.std::crypto::dsa::rpo_stark::deep_queries +use.std::crypto::dsa::rpo_stark::fri +use.std::crypto::dsa::rpo_stark::random_coin +use.std::crypto::dsa::rpo_stark::utils + + +# RPO-STARK-BASED SIGNATURE SCHEME VERIFICATION ALGORITHM +# ================================================================================================= + +#! Verifies a signature against a public key and a message. The procedure gets as inputs the public +#! key and the hash of the message via the operand stack. The signature is provided via the advice +#! stack. +#! +#! The signature is valid if and only if the procedure returns. +#! +#! Input: [PK, MSG, ...] +#! Output: [...] +#! +#! Cycles: ~ xx +export.verify + + #============================================================================================== + # I) Hash proof context and hash-&-load public inputs + #============================================================================================== + + # Initialize the seed using proof context and public inputs. + # This also saves the public inputs for later use + # + # Cycles: 56 + 54 = 110 + exec.constants::public_inputs_ptr + exec.random_coin::init_seed + #=> [C] + # TODO: This should be reseed_with_salt + exec.random_coin::reseed + #=> [...] + + #============================================================================================== + # II) Draw constraint composition coefficients + #============================================================================================== + + # Load main trace commitment and re-seed with it + # + # Cycles: 7 + 71 = 78 + padw + adv_loadw + exec.constants::main_trace_com_ptr mem_storew + #=> [main_trace_commitment] + exec.random_coin::reseed_with_salt + #=> [...] + + # Cycles: 204 + exec.constants::composition_coef_ptr + exec.random_coin::generate_constraint_composition_coefficients + #=> [...] + + #============================================================================================== + # IV) Reseed with commitment to constraint composition polynomial H evaluations over LDE + # and generate the Out-of-Domain (OOD) challenge z + #============================================================================================== + + # Reseed with constraint composition polynomial commitment + # + # Cycles: 7 + 71 + 101 = 179 + padw + adv_loadw + exec.constants::composition_poly_com_ptr mem_storew + exec.random_coin::reseed_with_salt + exec.random_coin::generate_z_zN + #=> [...] + + #============================================================================================== + # V) Read the OOD frames for the main trace, auxiliary trace and the trace of evaluations + # of H over the LDE domain. + #============================================================================================== + + # Cycles: 36 + exec.ood_frames::load_evaluation_frame + #=> [OOD_FRAME_HASH, ...] + + # Cycles: 71 + exec.random_coin::reseed_with_salt + + # Cycles: 160 + exec.ood_frames::load_constraint_evaluations + #=> [CONSTR_EVAL_HASH, ...] + + # Cycles: 71 + exec.random_coin::reseed_with_salt + + #============================================================================================== + # VI) Evaluate the constraints over the OOD frame and assert equality with H(z) + #============================================================================================== + + #============================================================================================== + # VII) FRI + #============================================================================================== + + #============================================ + # 1) Draw random coefficients for computing + # DEEP composition polynomial. + #============================================ + + # Cycles: 521 + exec.constants::deep_rand_coef_ptr + exec.random_coin::generate_deep_composition_random_coefficients + + #============================================ + # 2) Load and reseed with FRI layer commitments + # and draw the folding challenges for + # computing the degree respecting projection + #============================================ + + # Cycles: 273 + exec.utils::load_fri_layer_commitments + #=> [...] + + #============================================ + # 4) Remainder of size 32 verification: + # a) Check commitment to remainder polynomial + # coefficients. + # b) Load the NTT of remainder polynomial + # into memory. + # c) Check the NTT relationship. + #============================================ + + # Cycles: 1632 + exec.utils::load_and_verify_remainder + #=> [...] + + #============================================ + # 5) Check PoW nonce + #============================================ + + # Cycles: 73 + exec.random_coin::check_pow + #=> [...] + + #============================================ + # 6) Compute evaluations of DEEP composition + # polynomial at randomly chosen query positions + #============================================ + + # Compute the pointer to the first query using the pointer to + # the first layer commitment and total number of queries. + # + # Cycles: 5 + exec.constants::fri_com_ptr + exec.constants::num_fri_queries + dup movdn.2 + sub + #=> [query_ptr, num_queries, ...] + + # Draw random query indices + # + # Cycles: 487 + 31 * num_queries + swap dup.1 + exec.random_coin::generate_list_indices + #=> [query_ptr, ...] + + # Compute deep compostion polynomial queries + # + # Cycles: 6 + num_queries * 328 + exec.deep_queries::compute_deep_composition_polynomial_queries + #=> [query_ptr, ...] + + #============================================ + # 7) Call the FRI verifier + #============================================ + + # Get domain generator and pointers to the remainder + # codeword and first FRI layer commitment + # + # Cycles: 6 + exec.constants::lde_domain_generator + exec.constants::fri_com_ptr exec.constants::remainder_codeword_offset add + exec.constants::fri_com_ptr + movup.3 + #=> [query_ptr, fri_layer_ptr, remainder_ptr, domain_gen, ...] + + # Call FRI verifier + # + # Cycles: 7 + 4 + num_queries * (40 + num_layers * 81 + 26) + exec.fri::verify + #=> () +end diff --git a/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs b/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs index 911c23db34..8899e9b091 100644 --- a/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs +++ b/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs @@ -10,7 +10,7 @@ use test_utils::{ crypto::{MerklePath, NodeIndex, PartialMerkleTree, Rpo256 as MidenHasher}, group_slice_elements, math::fft, - Felt, FieldElement, MerkleTreeVC, QuadFelt as QuadExt, StarkField, EMPTY_WORD, + Felt, FieldElement, QuadFelt as QuadExt, StarkField, EMPTY_WORD, }; use winter_crypto::VectorCommitment; use winter_fri::{ diff --git a/stdlib/tests/crypto/stark/mod.rs b/stdlib/tests/crypto/stark/mod.rs index 0371cbf5bf..752e829829 100644 --- a/stdlib/tests/crypto/stark/mod.rs +++ b/stdlib/tests/crypto/stark/mod.rs @@ -1,32 +1,26 @@ use assembly::Assembler; -use miden_air::{Felt, FieldElement, FieldExtension, HashFunction, PublicInputs}; -use num::traits::sign; -use processor::{DefaultHost, Program, ProgramInfo, Word}; +use miden_air::{FieldExtension, HashFunction, PublicInputs}; +use processor::{DefaultHost, Program, ProgramInfo}; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use signature::{generate_advice_inputs_signature, VerifierData}; use test_utils::{ - crypto::{rpo_falcon512::PublicKey, rpo_stark::{PublicInputs as SignaturePublicInputs, SecretKey}}, math::{polynom, ExtensionOf}, prove, rand::{rand_array, rand_value}, verify, AdviceInputs, MemAdviceProvider, ProvingOptions, QuadFelt, StackInputs, VerifierError + crypto::rpo_stark::{PublicInputs as SignaturePublicInputs, SecretKey}, + prove, + rand::rand_array, + AdviceInputs, MemAdviceProvider, ProvingOptions, StackInputs, VerifierError, }; - mod verifier_recursive; -use verifier_recursive::{generate_advice_inputs, to_int_vec, QuadExt, }; +use verifier_recursive::generate_advice_inputs; mod signature; - - -// Note: Changes to MidenVM may cause this test to fail when some of the assumptions documented -// in `stdlib/asm/crypto/stark/verifier.masm` are violated. #[test] -#[ignore] fn signature_verification() { - let VerifierData { initial_stack, tape, store, advice_map } = generate_signature_data().unwrap(); - // Verify inside Miden VM let source = " use.std::crypto::dsa::rpo_stark::verifier begin @@ -39,30 +33,9 @@ fn signature_verification() { test.expect_stack(&[]); } -fn generate_signature_data() -> Result { - let seed = [0_u8; 32]; - let mut rng = ChaCha20Rng::from_seed(seed); - let sk = SecretKey::with_rng(&mut rng); - let sk = SecretKey::from_word(Word::default()); - - let message = Word::default(); - let signature = sk.sign(message); -//println!("signature {:?}", signature); - let pk = sk.compute_public_key(); - // signature.verify(message, pk.inner()); - let proof = signature.inner(); - - let pub_inputs = SignaturePublicInputs::new(pk.inner(), message); - - let res = generate_advice_inputs_signature(proof, pub_inputs); - // println!("res is {:?}", res); - Ok(res.unwrap()) -} - // Note: Changes to MidenVM may cause this test to fail when some of the assumptions documented // in `stdlib/asm/crypto/stark/verifier.masm` are violated. #[test] -#[ignore] fn stark_verifier_e2f4() { // An example MASM program to be verified inside Miden VM. // Note that output stack-overflow is not yet supported because of the way we handle public @@ -97,7 +70,24 @@ fn stark_verifier_e2f4() { test.expect_stack(&[]); } -// Helper function for recursive verification +/// Helper function for signature generation. +fn generate_signature_data() -> Result { + let seed = [0_u8; 32]; + let mut rng = ChaCha20Rng::from_seed(seed); + let sk = SecretKey::with_rng(&mut rng); + let pk = sk.compute_public_key(); + + let message = rand_array(); + let signature = sk.sign(message); + let proof = signature.inner(); + + let pub_inputs = SignaturePublicInputs::new(pk.inner(), message); + + let res = generate_advice_inputs_signature(proof, pub_inputs); + Ok(res.unwrap()) +} + +/// Helper function for recursive verification. pub fn generate_recursive_verifier_data( source: &str, stack_inputs: Vec, @@ -114,732 +104,10 @@ pub fn generate_recursive_verifier_data( let (stack_outputs, proof) = prove(&program, stack_inputs.clone(), &mut host, options).unwrap(); let program_info = ProgramInfo::from(program); - let res = - verify(program_info.clone(), stack_inputs.clone(), stack_outputs.clone(), proof.clone()) - .unwrap(); - println!("res of veri {:?}", res); + // build public inputs and generate the advice data needed for recursive proof verification let pub_inputs = PublicInputs::new(program_info, stack_inputs, stack_outputs); let (_, proof) = proof.into_parts(); Ok(generate_advice_inputs(proof, pub_inputs).unwrap()) } - -/* -poly 0 at (14281334308168704527, 10495222116659147228) is (10060846794257653263, 546027550684353096) -poly 1 at (14281334308168704527, 10495222116659147228) is (10903134704496183277, 5579342745194126910) -poly 2 at (14281334308168704527, 10495222116659147228) is (12893269862983042775, 17647699874671928675) -poly 3 at (14281334308168704527, 10495222116659147228) is (11122676875213712094, 5263064823292274143) -poly 4 at (14281334308168704527, 10495222116659147228) is (41855652377006736, 9909668281301462903) -poly 5 at (14281334308168704527, 10495222116659147228) is (14932615313904988467, 7592103672217106309) -poly 6 at (14281334308168704527, 10495222116659147228) is (20740824113534935, 3818898257924990209) -poly 7 at (14281334308168704527, 10495222116659147228) is (15272117991568816033, 14472765353298605242) -poly 8 at (14281334308168704527, 10495222116659147228) is (1409366930799599557, 4944651295747950778) -poly 9 at (14281334308168704527, 10495222116659147228) is (15967857750552075868, 2857971283248518823) -poly 10 at (14281334308168704527, 10495222116659147228) is (11602683508887447121, 18097224529377507115) -poly 11 at (14281334308168704527, 10495222116659147228) is (6426931889180492583, 17042609443108091430) -poly 12 at (14281334308168704527, 10495222116659147228) is (3787620295263208906, 5581463112448029526) -poly 13 at (14281334308168704527, 10495222116659147228) is (14819709244247351689, 9116944519363158237) -poly 14 at (14281334308168704527, 10495222116659147228) is (18258588819309979526, 12167294900610607376) -poly 15 at (14281334308168704527, 10495222116659147228) is (13323880019629950849, 16070006070861920166) -poly 16 at (14281334308168704527, 10495222116659147228) is (15088898314701251493, 17537315582941049748) -poly 17 at (14281334308168704527, 10495222116659147228) is (601580842485586130, 9327490444933127718) -poly 18 at (14281334308168704527, 10495222116659147228) is (2822984643375099546, 7202787223205524049) -poly 19 at (14281334308168704527, 10495222116659147228) is (14598635898512929731, 4144988733395143778) -poly 20 at (14281334308168704527, 10495222116659147228) is (17626662679135368322, 1223116119813894249) -poly 21 at (14281334308168704527, 10495222116659147228) is (4860278503993160809, 7161649524312813954) -poly 22 at (14281334308168704527, 10495222116659147228) is (5189975042430731858, 9217744093123510922) -poly 23 at (14281334308168704527, 10495222116659147228) is (3964029779034283138, 11151025876422081715) - -*/ - - -#[test] -fn second_mds_multiply() { - // Verify inside Miden VM - let source = " - use.std::crypto::dsa::rpo_stark::rpo_stark - begin - push.1000 - push.2.0.2.0 - repeat.3 - dup.4 add.1 swap.5 - mem_storew - end - - dropw - push.1.0.1.0 - repeat.3 - dup.4 add.1 swap.5 - mem_storew - end - - dropw drop - - push.14281334308168704527 push.10495222116659147228 - push.2000 push.1000 - exec.rpo_stark::multiply_mds_add_constant_apply_sbox_round - - add.2000 swap - - exec.rpo_stark::multiply_mds_add_constant - - push.3000 - padw - repeat.6 - dup.4 add.1 swap.5 - mem_loadw - movup.4 - padw - end - - - end - "; - - - let z = QuadExt::new(Felt::new(14281334308168704527), Felt::new(10495222116659147228)); - let mut ark = vec![]; - - for poly in ark1_polys { - let poly: Vec = poly - .iter() - .map(|coef| { - Felt::new(*coef) - - }) - .collect(); - let eval = polynom::eval(&poly, z); - - ark.push(eval); - } - //ark.reverse(); - let mut state: [QuadExt; 12] = [QuadExt::ONE; 12]; - state.iter_mut().take(6).for_each(|s| *s = s.double() ); - println!("state is {:?}", state); - //let mut initial_state = state.clone(); - apply_mds(&mut state); - add_constants(&mut state, &ark); - apply_sbox(&mut state); - - - let mut ark = vec![]; - - for poly in ark2_polys { - let poly: Vec = poly - .iter() - .map(|coef| { - Felt::new(*coef) - - }) - .collect(); - let eval = polynom::eval(&poly, z); - - ark.push(eval); - } - - apply_mds(&mut state); - add_constants(&mut state, &ark); - - let mut input_stack = vec![]; - input_stack.push(14281334308168704527_u64); - input_stack.push(10495222116659147228); - - //initial_state.reverse(); - //let tmp = to_int_vec( &initial_state) ; - - //let mut adv_stack = vec![]; - //adv_stack.extend_from_slice(&tmp); - - let test = build_test!(source, &[] ); - - - println!("res is {:?}", ark); - println!("state is {:?}", state); - test.expect_stack(&[]); -} -#[test] -fn multiply_mds_add_constant_apply_sbox_round() { - // Verify inside Miden VM - let source = " - use.std::crypto::dsa::rpo_stark::rpo_stark - begin - push.1000 - push.2.0.2.0 - repeat.3 - dup.4 add.1 swap.5 - mem_storew - end - - dropw - push.1.0.1.0 - repeat.3 - dup.4 add.1 swap.5 - mem_storew - end - - dropw drop - - push.14281334308168704527 push.10495222116659147228 - push.2000 push.1000 - exec.rpo_stark::multiply_mds_add_constant_apply_sbox_round - - push.2000 - padw - repeat.6 - dup.4 add.1 swap.5 - mem_loadw - movup.4 - padw - end - - - end - "; - - - let z = QuadExt::new(Felt::new(14281334308168704527), Felt::new(10495222116659147228)); - let mut ark = vec![]; - - for poly in ark1_polys { - let poly: Vec = poly - .iter() - .map(|coef| { - Felt::new(*coef) - - }) - .collect(); - let eval = polynom::eval(&poly, z); - - ark.push(eval); - } - //ark.reverse(); - let mut state: [QuadExt; 12] = [QuadExt::ONE; 12]; - state.iter_mut().take(6).for_each(|s| *s = s.double() ); - println!("state is {:?}", state); - //let mut initial_state = state.clone(); - apply_mds(&mut state); - add_constants(&mut state, &ark); - apply_sbox(&mut state); - - let mut input_stack = vec![]; - input_stack.push(14281334308168704527_u64); - input_stack.push(10495222116659147228); - - //initial_state.reverse(); - //let tmp = to_int_vec( &initial_state) ; - - //let mut adv_stack = vec![]; - //adv_stack.extend_from_slice(&tmp); - - let test = build_test!(source, &[] ); - - - println!("res is {:?}", ark); - println!("state is {:?}", state); - test.expect_stack(&[]); -} - -#[test] -fn multiply_double_extension_by_base() { - // Verify inside Miden VM - let source = " - use.std::crypto::dsa::rpo_stark::rpo_stark - begin - exec.rpo_stark::multiply_double_extension_by_base - end - "; - - let tau0 = rand_value::(); - let tau1 = rand_value::(); - let k0: Felt = rand_value(); - let k1: Felt = rand_value(); - let res0 = tau0.mul_base(k0); - let res1 = tau1.mul_base(k1); - let input_stack = vec![ - tau0.base_element(0).as_int(), - tau0.base_element(1).as_int(), - tau1.base_element(0).as_int(), - tau1.base_element(1).as_int(), - k0.as_int(), - k1.as_int(), - ]; - - let res = res0 + res1; - let output_stack = vec![res.base_element(1).as_int(), res.base_element(0).as_int()]; - - let test = build_test!(source, &input_stack); - test.expect_stack(&output_stack); -} - -#[test] -fn sbox() { - // Verify inside Miden VM - let source = " - use.std::crypto::dsa::rpo_stark::rpo_stark - begin - exec.rpo_stark::sbox - end - "; - - let tau = rand_value::(); - - let input_stack = vec![tau.base_element(0).as_int(), tau.base_element(1).as_int()]; - - let res = tau.exp((7_u32).into()); - let output_stack = vec![res.base_element(1).as_int(), res.base_element(0).as_int()]; - - let test = build_test!(source, &input_stack); - test.expect_stack(&output_stack); -} - -/* -coef is 8329032129963563016 -acc is (0, 0) -res is (8329032129963563016, 0) -coef is 8934619293596015107 -acc is (8329032129963563016, 0) -res is (5357259674621098529, 0) -coef is 15061243612815629935 -acc is (5357259674621098529, 0) -res is (18043538241885439730, 0) -coef is 17197876067442802066 -acc is (18043538241885439730, 0) -res is (15585052757326223702, 0) -coef is 16438925404421745533 -acc is (15585052757326223702, 0) -res is (4992160156068303057, 0) -coef is 3323980907020445132 -acc is (4992160156068303057, 0) -res is (4845877461879073039, 0) -coef is 15627700026530187867 -acc is (4845877461879073039, 0) -res is (16564465804631895702, 0) -coef is 2791148843003040487 -acc is (16564465804631895702, 0) -res is (13708779853286870332, 0) -poly 0 at (5904545740857336763, 2641448861188835256) is (13708779853286870332, 0) - -*/ -#[test] -fn evaluate_ark1_index_0_at_z() { - let source = " - use.std::crypto::dsa::rpo_stark::round_constants - begin - # => [tau1, tau0, dest_ptr, dest_ptr, ...] - - exec.round_constants::evaluate_ark1_index_0_at_z - # => [tau1, tau0, dest_ptr + 1, dest_ptr, ...] - - # Load the computed evaluation at tau - padw movup.7 mem_loadw - # => [0, 0, ev1, ev0, tau1, tau0, dest_ptr + 1, ...] - - # Clean up the stack - drop drop - # => [ev1, ev0, tau1, tau0, dest_ptr + 1, ...] - - # Fix overflow - movup.5 drop - end - "; - - let tau = QuadFelt::new(Felt::new(2358509191725100597), Felt::new(12448696411509285448)); - let ptr = 1000; - let ptr_nxt = 1001; - let res = QuadFelt::new(Felt::new(9108108481109559168), Felt::new(1381914921145369315)); - let input_stack = vec![ptr, ptr, tau.base_element(0).as_int(), tau.base_element(1).as_int()]; - - let output_stack = vec![ - res.base_element(1).as_int(), - res.base_element(0).as_int(), - tau.base_element(1).as_int(), - tau.base_element(0).as_int(), - ptr_nxt, - ]; - - let test = build_test!(source, &input_stack); - test.expect_stack(&output_stack); -} - -#[test] -fn evaluate_ark1_index_1_at_z() { - let source = " - use.std::crypto::dsa::rpo_stark::round_constants - begin - # => [tau1, tau0, dest_ptr, dest_ptr, ...] - - exec.round_constants::evaluate_ark1_index_1_at_z - # => [tau1, tau0, dest_ptr + 1, dest_ptr, ...] - - # Load the computed evaluation at tau - padw movup.7 mem_loadw - # => [0, 0, ev1, ev0, tau1, tau0, dest_ptr + 1, ...] - - # Clean up the stack - drop drop - # => [ev1, ev0, tau1, tau0, dest_ptr + 1, ...] - - # Fix overflow - movup.5 drop - end - "; - - let tau = QuadFelt::new(Felt::new(14281334308168704527), Felt::new(10495222116659147228)); - let ptr = 1000; - let ptr_nxt = 1001; - let res = QuadFelt::new(Felt::new(10903134704496183277), Felt::new(5579342745194126910)); - let input_stack = vec![ptr, ptr, tau.base_element(0).as_int(), tau.base_element(1).as_int()]; - - let output_stack = vec![ - res.base_element(1).as_int(), - res.base_element(0).as_int(), - tau.base_element(1).as_int(), - tau.base_element(0).as_int(), - ptr_nxt, - ]; - - let test = build_test!(source, &input_stack); - test.expect_stack(&output_stack); -} - -const ark1_polys: [[u64; 8]; 12] = [ - [ - 2791148843003040487, - 15627700026530187867, - 3323980907020445132, - 16438925404421745533, - 17197876067442802066, - 15061243612815629935, - 8934619293596015107, - 8329032129963563016, - ], - [ - 12374840782518234980, - 13067814063463246108, - 16444767378767684843, - 14102478245486764913, - 5721113686559987364, - 5550835267666484285, - 1140255260049705235, - 2940403776379367555, - ], - [ - 803239822289277331, - 92290315131409452, - 14504533961394498192, - 17449340622223708244, - 11641839262529699117, - 13830007435883778192, - 2171477269448177901, - 18024172012126180450, - ], - [ - 17259550729090128080, - 1436126261944143983, - 6827772059756176056, - 13633102721671278493, - 438808730725699483, - 5407974288453498850, - 8312944094443125539, - 12083646389987382742, - ], - [ - 16872030888212246909, - 10307413365916228519, - 5970696349452178882, - 3075676239487301499, - 6764475190363405683, - 12388465667776429451, - 5463940702410555170, - 4302341177141596798, - ], - [ - 13010646010715444756, - 13220880625440862351, - 15043202536693295725, - 12450612311725651741, - 1975121089721419805, - 17751579298152306599, - 5865829689316994740, - 10135856292008745804, - ], - [ - 11079243880688886569, - 13171475342452126305, - 16717118787075991203, - 12997762624630485971, - 2082764394649465048, - 2274009722649114980, - 11078166678912510243, - 14537022526074710084, - ], - [ - 6412175863526823473, - 7693358564819205804, - 12953861830888836611, - 942265184773461437, - 1607941585775238966, - 4379845611455349528, - 58856250008039951, - 16473125605159627119, - ], - [ - 5005263760224338834, - 11877952992388592984, - 13609269279460528668, - 12700182930600529552, - 13020259874513262126, - 1930782708828158469, - 5575776764248027070, - 12391274268940303373, - ], - [ - 11718820523788741765, - 59883440729546652, - 6312723811819661455, - 5308884009005395250, - 6182287153329169016, - 13207315343261220442, - 4815800570707034136, - 8349688098368982860, - ], - [ - 6043410183720093018, - 2126146309185433854, - 8378524768105627493, - 5544949132734068891, - 17681500018572116275, - 10699876530722034865, - 8011357321704081273, - 5725123156318075397, - ], - [ - 6223946836251310965, - 16586492306509623392, - 6856802671405566180, - 16479930990938214663, - 13641986601858015391, - 6665166827227923662, - 9454375281307822385, - 8412441953430543726, - ], -]; - - -const ark2_polys: [[u64; 8]; 12] = [[4644899059340455409, 2588000450744117712, 13105238537181697838, 9145530290182703923, 8318881075359001860, 2260425315804771343, 13140762909627491530, 10125751776384352797], -[1076805373481731514, 731771438168089372, 1451573959488719120, 7220138601034011484, 14518803097042109937, 8441003397118172058, 16691081699485452106, 13848563765445705020], -[10296796646521415185, 5634304416804201670, 2436250166439517097, 175122579984732489, 17819414171265412835, 11568691945480450310, 4685303716418085212, 9212910395839541860], -[13748310607328698306, 3231680637487443842, 11897908975989921011, 14948979053368640201, 788938329072261875, 2424518612267165880, 14447959571237460393, 17817850486374744537], -[430095072692583909, 3538460359490439815, 4910259163119359388, 13172964728236666704, 13264785748607221492, 9148793266208888638, 12523400296259625004, 1323646892185216842], -[17837225074619059476, 6702081431642835557, 15726014635140220142, 14804677398279293696, 17716100798530125807, 12274533074791157450, 454935568758037748, 3171283654084997195], -[2011206516638815708, 12992430013458659144, 8696495089799708930, 1400178508260896298, 4445028994876124043, 15086337211977579054, 2579568427157492470, 3842347926541387017], -[14455558190054243213, 9476151068182324219, 4476065032800445994, 4772948326559040143, 9999073914541559972, 8857261784008983684, 15200374878312346200, 12519281252880051360], -[15872839284583424888, 9158419513185267937, 989723691436384985, 3480674361312569156, 7972171312030024281, 6916765091459382631, 5174110470653655799, 10891579218396689814], -[3270022819064790682, 17115077542742512990, 12665325866539717707, 2141009619237002231, 9832785799742116087, 10808339012888707871, 17545443011752642513, 12528974695128465622], -[8849418171382398211, 1150833344352386619, 6870113859747343930, 13474841269676445703, 12213798227721715260, 12131307142274672056, 11958348010538656609, 6096042974457287451], -[17284012187876944133, 10339865060086263172, 12560365515943446953, 8769164948183307270, 11644987068425776572, 16184522505189623125, 1188079598780402137, 16980889739006603967]]; - -/// RPO MDS matrix -pub const MDS: [[Felt; STATE_WIDTH]; STATE_WIDTH] = [ - [ - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - ], - [ - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - ], - [ - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - ], - [ - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - ], - [ - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - ], - [ - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - ], - [ - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - ], - [ - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - ], - [ - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - Felt::new(26), - ], - [ - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - Felt::new(8), - ], - [ - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - Felt::new(23), - ], - [ - Felt::new(23), - Felt::new(8), - Felt::new(26), - Felt::new(13), - Felt::new(10), - Felt::new(9), - Felt::new(7), - Felt::new(6), - Felt::new(22), - Felt::new(21), - Felt::new(8), - Felt::new(7), - ], -]; - -const STATE_WIDTH:usize = 12; -pub fn add_constants>(state: &mut [E], ark: &[E]) { - - - for i in 0..STATE_WIDTH { - state[i] += ark[i]; - } - -} - - - -#[inline(always)] -fn apply_sbox>(state: &mut [E; STATE_WIDTH]) { - state.iter_mut().for_each(|v| { - let t2 = v.square(); - let t4 = t2.square(); - *v *= t2 * t4; - }); -} - -#[inline(always)] -fn apply_mds>(state: &mut [E; STATE_WIDTH]) { - let mut result = [E::ZERO; STATE_WIDTH]; - result.iter_mut().zip(MDS).for_each(|(r, mds_row)| { - state.iter().zip(mds_row).for_each(|(&s, m)| { - *r += E::from(m) * s; - }); - }); - *state = result -} diff --git a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs index 20539ae348..902ae9abe2 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs @@ -57,7 +57,7 @@ impl VerifierChannel { pow_nonce, num_unique_queries, gkr_proof: _, - salts, + salts: _, } = proof; // make AIR and proof base fields are the same diff --git a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs index 6d7cffd284..2ffe72c987 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs @@ -68,7 +68,6 @@ pub fn generate_advice_inputs( // generate the auxiliary random elements let mut aux_trace_rand_elements = vec![]; for commitment in trace_commitments.iter().skip(1) { - println!("aux_trace_com {:?}", commitment); let rand_elements: Vec = air .get_aux_rand_elements(&mut public_coin) .map_err(|_| VerifierError::RandomCoinError)?; From 2ff4b414d65f16cccacf350f644dc90b38956011 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Mon, 25 Nov 2024 05:47:55 +0100 Subject: [PATCH 10/19] wip: implement constraint check --- .../asm/crypto/dsa/rpo_stark/ood_frames.masm | 41 ++++++++++++++++++- .../crypto/dsa/rpo_stark/public_inputs.masm | 36 ---------------- .../asm/crypto/dsa/rpo_stark/random_coin.masm | 39 ++++++++++-------- stdlib/asm/crypto/dsa/rpo_stark/verifier.masm | 5 ++- 4 files changed, 66 insertions(+), 55 deletions(-) delete mode 100644 stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm diff --git a/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm b/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm index b042b73cff..567b086507 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm @@ -133,7 +133,7 @@ end #! Input: [...] #! Output: [res1, res0, ...] #! Cycles: 155 -export.compute_Hz +export.compute_Hz_old # Load the pointer to the OOD constraint polynomials evaluations exec.constants::ood_constraint_evals_ptr # => [ptr, ...] @@ -200,3 +200,42 @@ export.compute_Hz ext2mul ext2add end + +#! Computes the H(z) evaluation of the constraint composition polynomial at the OOD element z. +#! +#! Input: [coef_ptr, x1, x0, ...] +#! Output: [res1, res0, ...] +#! Cycles: 155 +export.compute_Hz + exec.constants::ood_constraint_evals_ptr add.11 + movdn.2 + push.0.0 + # => [acc1, acc0, x1, x0, coef_ptr, ...] + + repeat.6 + padw + dup.8 + mem_loadw + push.0 push.0 + dup.10 sub.2 swap.11 + sub.1 mem_loadw drop drop + # => [d1, d0, c1, c0, acc1, acc0, x1, x0, coef_ptr, ...] + + dup.7 dup.7 + # => [x1, x0, d1, d0, c1, c0, acc1, acc0, x1, x0, coef_ptr, ...] + + movup.7 movup.7 + # => [acc1, acc0, x1, x0, d1, d0, c1, c0, x1, x0, coef_ptr, ...] + ext2mul + # => [tmp1, tmp0, d1, d0, c1, c0, x1, x0, coef_ptr, ...] + + movup.5 movup.5 ext2add + # => [acc1, acc0, d1, d0, x1, x0, coef_ptr, ...] + + dup.5 dup.5 ext2mul ext2add + # => [acc1, acc0, x1, x0, coef_ptr, ...] + end + + movdn.4 movdn.4 + drop drop drop +end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm b/stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm deleted file mode 100644 index 6cb497ceb7..0000000000 --- a/stdlib/asm/crypto/dsa/rpo_stark/public_inputs.masm +++ /dev/null @@ -1,36 +0,0 @@ -use.std::crypto::dsa::rpo_stark::constants - - -#! Load the public inputs in memory starting from the address referenced by `public_inputs_ptr`. -#! In parallel, compute the hash of the public inputs being loaded. The hashing starts with -#! capacity registers of the hash function set to `C` resulting from hashing the proof context. -#! The ouptut D is the digest of the hashing. -#! -#! Input: [public_inputs_ptr, C] -#! Output: [D] -#! Cycles: 38 -export.load - - # TODO: load the public inputs using public_inputs_ptr - drop - - # Unhash the public inputs from the advice provider. - # The following assumes that the public inputs contain only the input and output states - # of the operand stack and both are of length exactly 16. - # TODO: generalize to any number of public inputs supported by the VM. - padw padw - repeat.4 - adv_loadw - swapw - adv_loadw - hperm - end - adv_loadw - swapw - exec.constants::zero_word mem_loadw - hperm - - dropw - swapw - dropw -end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm index 2ba509d0e3..c64ff6d434 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm @@ -442,26 +442,31 @@ export.generate_z_zN # Load z (first two felts of the random coin state) and log trace length N exec.constants::r1_ptr mem_loadw drop drop - push.8 - # => [log(trace_len), z_1, z_0, ...] - - dup.2 dup.2 - # => [z_1, z_0, log(trace_len), z_1, z_0, ...] - # TODO: Fix this part - # Compute z^N using the fact that z^N = z^(2^log(N)) - # Loop starts with `i=log(trace_len)` - push.1 - while.true - dup.1 dup.1 ext2mul - # => [(z_1, z_0)^n, i, z_1, z_0, ...] + dup.1 dup.1 - dup.2 sub.1 swap.3 push.1 neq - # => [b, (z_1, z_0)^n, i-1, z_1, z_0, ...] + dup.1 dup.1 + repeat.2 + dup.1 dup.1 + ext2mul + end + # => [z4_1, z4_0, z_1, z_0, ...] + dup.1 dup.1 + repeat.2 + dup.1 dup.1 + ext2mul + end + # => [z16_1, z16_0, z4_1, z4_0, z_1, z_0, z_1, z_0, ...] + + dup.5 dup.5 + repeat.7 + dup.1 dup.1 + ext2mul + end + # => [z16_1, z16_0, z16_1, z16_0, z4_1, z4_0, z_1, z_0, z_1, z_0, ...] + repeat.3 + ext2mul end - - movup.2 drop - # => [(z_1, z_0)^n, z_1, z_0, ...] # Store z and z^N exec.constants::z_ptr mem_storew diff --git a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm index 73d24eb47c..c622346c35 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm @@ -88,11 +88,14 @@ export.verify # Cycles: 71 exec.random_coin::reseed_with_salt + #=> [...] #============================================================================================== # VI) Evaluate the constraints over the OOD frame and assert equality with H(z) #============================================================================================== + #=> [...] + #============================================================================================== # VII) FRI #============================================================================================== @@ -161,7 +164,7 @@ export.verify # Compute deep compostion polynomial queries # - # Cycles: 6 + num_queries * 328 + # Cycles: 24 + num_queries * 315 exec.deep_queries::compute_deep_composition_polynomial_queries #=> [query_ptr, ...] From b606b64a48449445894f78ac369c294b60dceba8 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Mon, 25 Nov 2024 05:51:51 +0100 Subject: [PATCH 11/19] wip --- Cargo.lock | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 33c9f3e70f..1a1a3605f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1060,7 +1060,6 @@ dependencies = [ "num", "num-complex", "rand", - "rand_chacha", "rand_core", "sha3", "winter-crypto 0.10.2", @@ -2879,17 +2878,6 @@ dependencies = [ "winter-utils 0.11.0", ] -[[package]] -name = "winterfell" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c8336dc6a035698780b8cc624f875e479bd6bf6e1846670f3ef4485c125882" -dependencies = [ - "winter-air", - "winter-prover", - "winter-verifier", -] - [[package]] name = "yansi" version = "1.0.1" From cefe86688c06224983284d0d0de4887b3cfd04a1 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:03:22 +0100 Subject: [PATCH 12/19] feat: fully working RPO STARK-based signature MASM verifier --- Cargo.lock | 20 +- Cargo.toml | 20 +- core/src/lib.rs | 3 +- processor/src/operations/comb_ops.rs | 4 +- processor/src/stack/mod.rs | 3 - prover/src/lib.rs | 18 +- .../asm/crypto/dsa/rpo_stark/constants.masm | 213 ++- .../dsa/rpo_stark/constraints_evaluation.masm | 338 +++++ .../crypto/dsa/rpo_stark/deep_queries.masm | 101 +- stdlib/asm/crypto/dsa/rpo_stark/mds_sbox.masm | 1304 +++++++++++++++++ .../asm/crypto/dsa/rpo_stark/ood_frames.masm | 161 +- .../dsa/rpo_stark/permutation_constants.masm | 1292 ++++++++++++++++ .../asm/crypto/dsa/rpo_stark/random_coin.masm | 41 +- .../round_constants_polynomials.masm | 1157 +++++++++++++++ stdlib/asm/crypto/dsa/rpo_stark/utils.masm | 136 +- stdlib/asm/crypto/dsa/rpo_stark/verifier.masm | 13 +- stdlib/tests/crypto/fri/verifier_fri_e2f4.rs | 15 +- stdlib/tests/crypto/stark/mod.rs | 1 - .../tests/crypto/stark/signature/channel.rs | 442 ++++++ stdlib/tests/crypto/stark/signature/mod.rs | 189 +++ .../stark/verifier_recursive/channel.rs | 2 +- test-utils/src/lib.rs | 2 +- 22 files changed, 5067 insertions(+), 408 deletions(-) create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/mds_sbox.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/permutation_constants.masm create mode 100644 stdlib/asm/crypto/dsa/rpo_stark/round_constants_polynomials.masm create mode 100644 stdlib/tests/crypto/stark/signature/channel.rs create mode 100644 stdlib/tests/crypto/stark/signature/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1a1a3605f4..bfad78bbae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1053,6 +1053,7 @@ dependencies = [ [[package]] name = "miden-crypto" version = "0.12.0" +source = "git+https://github.com/0xPolygonMiden/crypto?branch=al-stark-signature-dev-masm#eaa1db66fbef27a2fea35586a425dc29fe421108" dependencies = [ "blake3", "cc", @@ -1060,6 +1061,7 @@ dependencies = [ "num", "num-complex", "rand", + "rand_chacha", "rand_core", "sha3", "winter-crypto 0.10.2", @@ -2744,11 +2746,9 @@ dependencies = [ [[package]] name = "winter-air" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8fdb702503625f54dcaf9222aa2c7a0b2e868b3eb84b90d1837d68034bf999" +version = "0.10.0" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#c6542eb717e73baaeda156dafe0ab187089a995f" dependencies = [ - "libc-print", "libm", "winter-crypto 0.11.0", "winter-fri", @@ -2827,7 +2827,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c2f3cf80955f084fd614c86883195331116b6c96dc88532d43d6836bd7adee" dependencies = [ - "libc-print", "rand", "rand_chacha", "tracing", @@ -2870,7 +2869,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56d949eab6c26328733477ec56ca054fdc69c0c1b8267fa03d8b618ffe2193c4" dependencies = [ - "libc-print", "winter-air", "winter-crypto 0.11.0", "winter-fri", @@ -2878,6 +2876,16 @@ dependencies = [ "winter-utils 0.11.0", ] +[[package]] +name = "winterfell" +version = "0.10.0" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#c6542eb717e73baaeda156dafe0ab187089a995f" +dependencies = [ + "winter-air", + "winter-prover", + "winter-verifier", +] + [[package]] name = "yansi" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 354eea6ac5..0c3db8a4bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,14 +35,14 @@ overflow-checks = true [patch.crates-io] -winter-air = {path = "../../training/test_task/winterfell/air" } -winter-crypto = {path = "../../training/test_task/winterfell/crypto" } -winter-prover = {path = "../../training/test_task/winterfell/prover" } -winter-verifier = {path = "../../training/test_task/winterfell/verifier" } -winter-math = {path = "../../training/test_task/winterfell/math" } -winter-fri = {path = "../../training/test_task/winterfell/fri" } -winter-maybe-async = {path = "../../training/test_task/winterfell/utils/maybe_async" } -winter-utils = {path = "../../training/test_task/winterfell/utils/core" } -winter-rand-utils = {path = "../../training/test_task/winterfell/utils/rand" } +winter-air = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-crypto = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-prover = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-verifier = { git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-math = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-fri = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-maybe-async = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-utils = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-rand-utils = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -miden-crypto = {path = "../../work/crypto" } +miden-crypto = {git = 'https://github.com/0xPolygonMiden/crypto', branch = 'al-stark-signature-dev-masm' } diff --git a/core/src/lib.rs b/core/src/lib.rs index 1f981c50d5..d04564cfd4 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -84,8 +84,7 @@ pub mod crypto { } pub mod dsa { - pub use miden_crypto::dsa::rpo_falcon512; - pub use miden_crypto::dsa::rpo_stark; + pub use miden_crypto::dsa::{rpo_falcon512, rpo_stark}; } } diff --git a/processor/src/operations/comb_ops.rs b/processor/src/operations/comb_ops.rs index aab8c70468..498026f038 100644 --- a/processor/src/operations/comb_ops.rs +++ b/processor/src/operations/comb_ops.rs @@ -362,10 +362,10 @@ mod tests { expected.extend_from_slice(&[ZERO, Felt::from(18_u8), Felt::from(10_u8), Felt::from(2_u8)]); // updated accumulators expected.extend_from_slice(&[ - p.to_base_elements()[0], - p.to_base_elements()[1], r.to_base_elements()[0], r.to_base_elements()[1], + p.to_base_elements()[0], + p.to_base_elements()[1], ]); // the top 8 stack elements should equal tx since 8 calls to `rcomb_base` implies 8 circular // shifts of the top 8 elements i.e., the identity map on the top 8 element. diff --git a/processor/src/stack/mod.rs b/processor/src/stack/mod.rs index a8979f09a1..ad133e48cb 100644 --- a/processor/src/stack/mod.rs +++ b/processor/src/stack/mod.rs @@ -1,5 +1,3 @@ -use std::println; - use alloc::vec::Vec; use miden_air::RowIndex; @@ -135,7 +133,6 @@ impl Stack { /// # Errors /// Returns an error if the overflow table is not empty at the current clock cycle. pub fn build_stack_outputs(&self) -> Result { - println!("stak is {:?}", self.get_state_at(self.clk)); if self.overflow.num_active_rows() != 0 { return Err(ExecutionError::OutputStackOverflow(self.overflow.num_active_rows())); } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 34c39bd367..dd8026d214 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -19,7 +19,6 @@ use processor::{ math::{Felt, FieldElement}, ExecutionTrace, Program, }; -use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use tracing::instrument; use winter_air::ZkParameters; use winter_maybe_async::{maybe_async, maybe_await}; @@ -40,7 +39,7 @@ pub use processor::{ crypto, math, utils, AdviceInputs, Digest, ExecutionError, Host, InputError, MemAdviceProvider, StackInputs, StackOutputs, Word, }; -pub use winter_prover::{crypto::MerkleTree as MerkleTreeVC, Proof}; +pub use winter_prover::{crypto::MerkleTree as MerkleTreeVC, MockPrng, Proof}; // PROVER // ================================================================================================ @@ -89,7 +88,7 @@ pub fn prove( stack_inputs, stack_outputs.clone(), ); - maybe_await!(prover.prove(trace)) + maybe_await!(prover.prove(trace, None)) }, HashFunction::Blake3_256 => { let prover = ExecutionProver::>::new( @@ -97,7 +96,7 @@ pub fn prove( stack_inputs, stack_outputs.clone(), ); - maybe_await!(prover.prove(trace)) + maybe_await!(prover.prove(trace, None)) }, HashFunction::Rpo256 => { let prover = ExecutionProver::::new( @@ -107,7 +106,7 @@ pub fn prove( ); #[cfg(all(feature = "metal", target_arch = "aarch64", target_os = "macos"))] let prover = gpu::metal::MetalExecutionProver::new(prover, HashFn::Rpo256); - maybe_await!(prover.prove(trace)) + maybe_await!(prover.prove(trace, None)) }, HashFunction::Rpx256 => { let prover = ExecutionProver::::new( @@ -117,7 +116,7 @@ pub fn prove( ); #[cfg(all(feature = "metal", target_arch = "aarch64", target_os = "macos"))] let prover = gpu::metal::MetalExecutionProver::new(prover, HashFn::Rpx256); - maybe_await!(prover.prove(trace)) + maybe_await!(prover.prove(trace, None)) }, } .map_err(ExecutionError::ProverError)?; @@ -194,6 +193,7 @@ where DefaultConstraintEvaluator<'a, ProcessorAir, E>; type ConstraintCommitment> = DefaultConstraintCommitment; + type ZkPrng = MockPrng; fn options(&self) -> &WinterProofOptions { &self.options @@ -221,10 +221,10 @@ where main_trace: &ColMatrix, domain: &StarkDomain, partition_options: PartitionOptions, - zk_parameters: Option + zk_parameters: Option, + prng: &mut Option, ) -> (Self::TraceLde, TracePolyTable) { - let mut prng = ChaCha20Rng::from_entropy(); - DefaultTraceLde::new(trace_info, main_trace, domain, partition_options, zk_parameters, &mut prng) + DefaultTraceLde::new(trace_info, main_trace, domain, partition_options, zk_parameters, prng) } #[maybe_async] diff --git a/stdlib/asm/crypto/dsa/rpo_stark/constants.masm b/stdlib/asm/crypto/dsa/rpo_stark/constants.masm index a0419e1a2a..93edf4147e 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/constants.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/constants.masm @@ -1,18 +1,44 @@ # CONSTANTS # ================================================================================================= -# General constants const.ROOT_UNITY=7277203076849721926 const.DOMAIN_OFFSET=7 const.DOMAIN_OFFSET_INV=2635249152773512046 +const.MINUS_ONE=18446744069414584320 +const.BLOWUP_FACTOR=8 +const.FRI_FOLDING_FACTOR=4 +const.FRI_LOG_FOLDING_FACTOR=2 +# Instant-specific constants +# Changing the number of queries has a cascading effect on the following constants. The reason for +# this is related to the dependence of the degree of the zero-knowledge randomizing polynomial on +# the number of FRI queries. +# Moreover, the changes also affect the following places: +# +# 1. Seed initialization in `random_coin::init_seed`. +# 2. The number of constraint composition segment polynomial, which affects: +# a. The power `N` in `random_coin::generate_z_zN` +# b. The size of the constraint OOD frame in `ood_frames::load_constraint_evaluations` +# c. The size of the trace domain and LDE domains. +# d. The size of the remainder polynomial and remainder codewords in `exec.utils::load_and_verify_remainder` +# e. The size of the constraint composition frame for each DEEP query, which affects: +# i) The hashing and storing of the constraint composition part in `load_query_row` +# ii) Computing the random linear combination in `combine_constraint_poly_columns` +const.NUM_FRI_QUERIES=30 +const.NUM_FRI_LAYERS=2 +const.REMAINDER_CODEWORD_OFFSET=4 # this is two times NUM_FRI_LAYERS +const.SIZE_OF_REMAINDER_CODEWORD=64 +const.SIZE_OF_REMAINDER_CODEWORD_DIV_BY_2=32 +const.INITIAL_LDE_SIZE=1024 +const.INITIAL_LDE_LOG_SIZE=10 +const.TRACE_DOMAIN_GEN=16777216 +const.MINUS_DOMAIN_GEN_POW_7=1099511627520 +const.LDE_DOMAIN_GEN=4255134452441852017 +const.GRINDING_FACTOR=12 # MEMORY POINTERS # ================================================================================================= -# Trace domain generator -const.TRACE_DOMAIN_GENERATOR_PTR=4294799999 - # Public inputs const.PUBLIC_INPUTS_PTR=4294800000 @@ -23,57 +49,49 @@ const.OOD_TRACE_PTR=4294900000 const.OOD_CONSTRAINT_EVALS_PTR=4294900012 # Current trace row -# 70 Felt for main portion of trace, 7 * 2 Felt for auxiliary portion of trace and 8 * 2 Felt for -# constraint composition polynomials. Since we store these with the padding to make each of the -# three portions a multiple of 8, the number of slots required is (72 + 16 + 16) / 4 = 26 +# 12 Felt for main portion of trace and 12 * 2 Felt for constraint composition polynomials. +# There is also one extension field element corresponding to the randomizer polynomial. const.CURRENT_TRACE_ROW_PTR=4294900100 # We need 2 Felt for each constraint. We take 2800 slots as an upper bound const.COMPOSITION_COEF_PTR=4294900200 -# We need 2 Felt for each trace column and each of the 8 constraint composition columns. We thus need -# (70 + 7 + 8) * 2 Felt i.e. 43 memory slots. +# We need 2 Felt for each trace column and each of the 12 constraint composition columns. We thus need +# (12 + 12) * 2 Felt i.e. 6 memory slots. const.DEEP_RAND_CC_PTR=4294903000 # FRI # -# (FRI_COM_PTR - 100) ---| +# (FRI_COM_PTR - NUM_FRI_QUERIES) ---| # . -# . | <- FRI queries +# . | <- FRI queries # . -# FRI_COM_PTR ---| +# FRI_COM_PTR ---| # . -# . | <- FRI layer commitments and folding challenges +# . | <- FRI layer commitments and folding challenges # . -# (FRI_COM_PTR + 32) ---| +# (FRI_COM_PTR + 32) ---| # . -# . | <- Remainder codeword and polynomial +# . | <- Remainder codeword and polynomial # . -# (FRI_COM_PTR + 66-1) ---| +# (FRI_COM_PTR + 66-1) ---| # # For each FRI layer, we need 2 memory slots, one for storing the FRI layer commitment and one for # storing the word [a0, a1, log2(lde_size), lde_size] where a := (a0, a1) is the folding randomness # and lde_size is the size of the LDE domain. Since we are using a folding factor of 4 and the -# maximal degree of the remainder polynomial that we allow is 7, an upper limit of 16 FRI layers is -# ample and the number of memory slots we thus allocate for this is 32. Moreover, we allocate -# an additional 32 slots for the remainder codeword and 2 for the remainder polynomial. These are -# expected to be laid out right after the FRI commitments. -# The total number of slots thus becomes 66. +# maximal degree of the remainder polynomial that we allow is 15, an upper limit of 4 FRI layers is +# ample and the number of memory slots we thus allocate for this is 8. Moreover, we allocate +# an additional maximum 64 slots for the remainder codeword and maximum 4 for the remainder polynomial. +# These are expected to be laid out right after the FRI commitments. +# The total number of slots thus becomes 72. const.FRI_COM_PTR=4294903200 # Commitment to main, auxiliary and composition polynomials traces const.MAIN_TRACE_COM_PTR=4294903300 const.COMPOSITION_POLY_COM_PTR=4294903301 -# Instant-specific constants -const.NUM_FRI_QUERIES=100 -const.REMAINDER_CODEWORD_OFFSET=6 -const.LDE_SIZE_PTR=4294903303 +# The OOD point as well as z^N const.Z_PTR=4294903304 -const.NUM_QUERIES_PTR=4294903305 -const.TRACE_LENGTH_PTR=4294903306 -const.TRACE_LENGTH_LOG_PTR=4294903307 -const.GRINDING_FACTOR_PTR=4294903308 # RPO capacity initialization words const.ZERO_WORD_PTR=4294903309 @@ -89,38 +107,22 @@ const.TMP1=4294903315 const.TMP2=4294903316 const.TMP3=4294903317 const.TMP4=4294903318 -const.TMP5=4294903319 -const.TMP6=4294903320 -const.TMP7=4294903321 -const.TMP8=4294903322 -const.TMP9=4294903323 -const.TMP10=4294903324 -const.TMP11=4294903325 - # The following is a table summarizing the memory pointers used: # +------------------------------------------+-------------------------+ # | ID | Address | # +------------------------------------------+-------------------------+ -# | TRACE_DOMAIN_GENERATOR_PTR | 4294799999 | # | PUBLIC_INPUTS_PTR | 4294800000 | # | OOD_TRACE_PTR | 4294900000 | # | OOD_CONSTRAINT_EVALS_PTR | 4294900077 | # | CURRENT_TRACE_ROW_PTR | 4294900100 | -# | AUX_RAND_ELEM_PTR | 4294900150 | # | COMPOSITION_COEF_PTR | 4294900200 | # | DEEP_RAND_CC_PTR | 4294903000 | # | FRI_COM_PTR | 4294903200 | # | MAIN_TRACE_COM_PTR | 4294903300 | -# | AUX_TRACE_COM_PTR | 4294903301 | -# | COMPOSITION_POLY_COM_PTR | 4294903302 | -# | LDE_SIZE_PTR | 4294903303 | +# | COMPOSITION_POLY_COM_PTR | 4294903301 | # | Z_PTR | 4294903304 | -# | NUM_QUERIES_PTR | 4294903305 | -# | TRACE_LENGTH_PTR | 4294903306 | -# | TRACE_LENGTH_LOG_PTR | 4294903307 | -# | GRINDING_FACTOR_PTR | 4294903308 | # | ZERO_WORD_PTR | 4294903309 | # | ZERO_ZERO_ZERO_FOUR_PTR | 4294903310 | # | C_PTR | 4294903311 | @@ -130,33 +132,51 @@ const.TMP11=4294903325 # | TMP2 | 4294903316 | # | TMP3 | 4294903317 | # | TMP4 | 4294903318 | -# | TMP5 | 4294903319 | -# | TMP6 | 4294903320 | -# | TMP7 | 4294903321 | -# | TMP8 | 4294903322 | -# | TMP9 | 4294903323 | # +------------------------------------------+-------------------------+ # ACCESSORS # ================================================================================================= -# Procedure to push the trace domain generator address to the stack. -# -# Input: [...] -# Output: [ptr, ...] wher ptr is the memory address of the trace domain generator -# Cycles: 1 -export.trace_domain_generator_ptr - push.TRACE_DOMAIN_GENERATOR_PTR -end - export.domain_offset push.DOMAIN_OFFSET end +export.blowup_factor + push.BLOWUP_FACTOR +end + +export.grinding_factor + push.GRINDING_FACTOR +end + export.num_fri_queries push.NUM_FRI_QUERIES end +export.number_of_fri_layers + push.NUM_FRI_LAYERS +end + +export.folding_factor + push.FRI_FOLDING_FACTOR +end + +export.log_folding_factor + push.FRI_LOG_FOLDING_FACTOR +end + +export.initial_lde_domain_size + push.INITIAL_LDE_SIZE +end + +export.initial_lde_domain_log_size + push.INITIAL_LDE_LOG_SIZE +end + +export.remainder_codeword_size_div_by_2 + push.SIZE_OF_REMAINDER_CODEWORD_DIV_BY_2 +end + export.remainder_codeword_offset push.REMAINDER_CODEWORD_OFFSET end @@ -166,11 +186,19 @@ export.domain_offset_inv end export.trace_domain_generator - push.16777216 + push.TRACE_DOMAIN_GEN end export.lde_domain_generator - push.9113133275150391358 + push.LDE_DOMAIN_GEN +end + +export.minus_one + push.MINUS_ONE +end + +export.minus_domain_gen_pow_7 + push.MINUS_DOMAIN_GEN_POW_7 end export.public_inputs_ptr @@ -209,13 +237,6 @@ export.composition_poly_com_ptr push.COMPOSITION_POLY_COM_PTR end -#! Address to store details about the lde size. -#! -#! Memory is `[lde_size, log(lde_size), lde_g, 0]` -export.lde_size_ptr - push.LDE_SIZE_PTR -end - #! Address for the point `z` and its exponentiation `z^N` where `N=trace_len`. #! #! Memory is `[(z_1, z_0)^n, z_1, z_0]` @@ -223,26 +244,13 @@ export.z_ptr push.Z_PTR end -export.number_queries_ptr - push.NUM_QUERIES_PTR -end - -export.trace_length_ptr - push.TRACE_LENGTH_PTR -end - -export.trace_length_log_ptr - push.TRACE_LENGTH_LOG_PTR -end - -export.grinding_factor_ptr - push.GRINDING_FACTOR_PTR -end - +#! Load the capacity initialization state when the length of the hashed sequence is divisible by 8. export.zero_word push.ZERO_WORD_PTR end +#! Load the capacity initialization state when the length of the hashed sequence is equal +#! to 4 modulo 8. export.zero_zero_zero_four_word push.ZERO_ZERO_ZERO_FOUR_PTR end @@ -271,49 +279,22 @@ export.r2_ptr push.R2_PTR end -#! Address to store details to compute deep query denominators. -#! -#! Memory is `[gz1, gz0, z_1, z_0]` +#! Address to store temporary values. export.tmp1 push.TMP1 end +#! Address to store temporary values. export.tmp2 push.TMP2 end +#! Address to store temporary values. export.tmp3 push.TMP3 end +#! Address to store temporary values. export.tmp4 push.TMP4 end - -export.tmp5 - push.TMP5 -end - -export.tmp6 - push.TMP6 -end - -export.tmp7 - push.TMP7 -end - -export.tmp8 - push.TMP8 -end - -export.tmp9 - push.TMP9 -end - -export.tmp10 - push.TMP10 -end - -export.tmp11 - push.TMP11 -end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm b/stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm new file mode 100644 index 0000000000..5a7e9432fe --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm @@ -0,0 +1,338 @@ +use.std::crypto::dsa::rpo_stark::mds_sbox +use.std::crypto::dsa::rpo_stark::constants +use.std::crypto::dsa::rpo_stark::ood_frames + +#! Performs the DEEP consistency check at the out-of-domain point. +#! +#! +#! Input: [...] +#! Output: [...] +#! +#! Cycles: ~ 8320 +export.deep_consistency_check + padw exec.constants::z_ptr mem_loadw + exec.ood_frames::compute_Hz + # => [Hz1, Hz0, z1, z0, ...] + + exec.constants::public_inputs_ptr add.1 + exec.constants::composition_coef_ptr + # => [rnd_ptr, pk_ptr, Hz1, Hz0, z1, z0, ...] + movup.5 movup.5 + exec.constants::ood_trace_ptr + # => [ood_ptr, z1, z0, rnd_ptr, pk_ptr, Hz1, Hz0, ...] + exec.evaluate_constraints + + movup.2 assert_eq + assert_eq + dropw +end + +#! Evaluates constraints, both transitional and boundary, linearly combines then and divides by +#! their appropriate divisors. +#! +#! Input: [ood_ptr, z1, z0, rnd_ptr, pk_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: ~ 7975 +export.evaluate_constraints.24 + + # Split the trace OOD evaluation frame into a current portion and a next portion + locaddr.0 dup add.6 + # => [ood_cur_ptr, ood_nxt_ptr, ood_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + exec.disentangle_ood_frame + # => [z1, z0, rnd_ptr, pk_ptr, ...] + + # Apply the first half of the RPO constraint + locaddr.0 dup add.6 + dup.3 dup.3 + # => [z1, z0, ood_cur_ptr, ood_nxt_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + locaddr.0 add.12 + # => [res_ptr, z1, z0, ood_cur_ptr, ood_nxt_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + dup.3 + # => [ood_cur_ptr, res_ptr, z1, z0, ood_cur_ptr, ood_nxt_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + + exec.mds_sbox::multiply_mds_add_constant_apply_sbox_round + # => [ood_cur_ptr, ood_nxt_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + dup.3 dup.3 + locaddr.0 add.18 + locaddr.0 add.12 + exec.mds_sbox::multiply_mds_add_constant + + # Apply the second half of the RPO constraint + dup.4 + # => [rnd_ptr, ood_cur_ptr, ood_nxt_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + locaddr.0 add.18 + # => [res_ptr, rnd_ptr, ood_cur_ptr, ood_nxt_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + movup.3 + # => [ood_nxt_ptr, res_ptr, rnd_ptr, ood_cur_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + exec.mds_sbox::sbox_next_and_compute_random_linear_combination + # => [tr_num1, tr_num0, ood_cur_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + + # Divide by the transition constraints divisor + dup.4 dup.4 + # => [z1, z0, tr_num1, tr_num0, ood_cur_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + exec.divide_transition_divisor + # => [val1, val0, ood_cur_ptr, z1, z0, rnd_ptr, pk_ptr, ...] + + # Movup the pointer to the public key and the pointer to the randomness to batch + # boundary constraints. + movup.6 movup.6 add.6 + # => [rnd_ptr, pk_ptr, val1, val0, ood_cur_ptr, z1, z0, ...] + + # We need the pointer to the current row of the OOD frame + movup.4 + # => [ood_cur_ptr, rnd_ptr, pk_ptr, val1, val0, z1, z0, ...] + + # Compute the combined numerator for boundary constraints against first trace row + exec.compute_boundary_initial_step + # => [bnd_first1, bnd_first0, ood_cur_ptr, rnd_ptr, pk_ptr, val1, val0, z1, z0, ...] + + # Compute the combined numerator for boundary constraints against last tace row + movdn.4 movdn.4 + exec.compute_boundary_final_step + # => [bnd_last1, bnd_last0, bnd_first1, bnd_first0, val1, val0, z1, z0, ...] + + # Divide numerator + dup.7 dup.7 + # => [z1, z0, bnd_last1, bnd_last0, bnd_first1, bnd_first0, val1, val0, z1, z0, ...] + exec.divide_boundary_last + # => [tmp1, tmp0, bnd_first1, bnd_first0, val1, val0, z1, z0, ...] + + # Divide numerator + movup.3 movup.3 movup.7 movup.7 + # => [z1, z0, bnd_first1, bnd_first0, tmp1, tmp0, val1, val0, ...] + exec.divide_boundary_first + # => [tmp1, tmp0, tmp1, tmp0, val1, val0, ...] + + # Compute the final result + ext2add ext2add + # => [res1, res0, ...] +end + +#! Given the OOD evaluation frame of the main trace polynomials, which is stored at address +#! `ood_ptr` with the current and next rows interleaved, the following procedure disentangles +#! the current row from the main row and saves them in `ood_cur_ptr` and `ood_nxt_ptr`, +#! respectively. +#! +#! Input: [ood_cur_ptr, ood_nxt_ptr, ood_ptr, ...] +#! Output: [...] +#! Cycles: ~ 270 +export.disentangle_ood_frame + padw padw + # => [X, X, ood_cur_ptr, ood_nxt_ptr, ood_ptr, ...] + + repeat.6 + dup.10 mem_loadw + # => [x1, x0, a1, a0, X, ood_cur_ptr, ood_nxt_ptr, ood_ptr, ...] + + swapw dup.10 add.2 swap.11 add.1 mem_loadw + # => [y1, y0, b1, b0, x1, x0, a1, a0, ood_cur_ptr, ood_nxt_ptr, ood_ptr + 2, ...] + + movup.7 movup.7 movup.5 movup.5 + # => [b1, b0, a1, a0, y1, y0, x1, x0, ood_cur_ptr, ood_nxt_ptr, ood_ptr + 2, ...] + + dup.8 add.1 swap.9 mem_storew + # => [b1, b0, a1, a0, y1, y0, x1, x0, ood_cur_ptr + 1, ood_nxt_ptr, ood_ptr + 2, ...] + + swapw dup.9 add.1 swap.10 mem_storew + # => [y1, y0, x1, x0, b1, b0, a1, a0, ood_cur_ptr + 1, ood_nxt_ptr + 1, ood_ptr + 2, ...] + end + + dropw dropw drop drop drop + # => [...] +end + +#! Divides the linearly combined evaluations of transitional constraints by their common divisor. +#! +#! Input: [z1, z0, tr_num1, tr_num0, ...] +#! Output: [val1, val0, ...] +#! +#! Cycles: 43 +export.divide_transition_divisor + + # Compute z^8 + dup.1 dup.1 + repeat.3 + dup.1 dup.1 + ext2mul + end + # => [z81, z80, z1, z0, tr_num1, tr_num0, ...] + + # Multiply by (z - g^(8 - 1)) + movdn.5 movdn.5 + # => [z1, z0, tr_num1, tr_num0, z81, z80, ...] + swap add.1099511627520 swap ext2mul + # => [num1, num0, z81, z80, ...] + + # Divide by (z^8 - 1) + movup.3 add.18446744069414584320 movup.3 + # => [den1, den0, num1, num0, ...] + ext2div +end + +#! Computes the linearly combined evaluations of boundary constraints against first trace row. +#! +#! Input: [ood_cur_ptr, rnd_ptr, ...] +#! Output: [bnd_first1, bnd_first0, ood_cur_ptr, rnd_ptr, ...] +#! +#! Cycles: 190 +export.compute_boundary_initial_step + dup.1 dup.1 + repeat.2 + exec.load_and_multiply_tuples_ext2 + end + + add.2 + + repeat.2 + exec.load_and_multiply_tuples_ext2 + end + drop drop + + repeat.3 + ext2add + end +end + +#! Computes the linearly combined evaluations of boundary constraints against final trace row. +#! +#! Input: [ood_cur_ptr, rnd_ptr, pk_ptr, ...] +#! Output: [bnd_last1, bnd_last0, ...] +#! +#! Cycles: 108 +export.compute_boundary_final_step + + add.2 swap add.4 swap + # => [ood_cur_ptr, rnd_ptr, pk_ptr, ...] + + # Compute the first two terms of the numerator + + padw + dup.4 mem_loadw + # => [w1, w0, v1, v0, ood_cur_ptr, rnd_ptr, pk_ptr, ...] + padw movup.10 mem_loadw + # => [q1, q0, p1, p0, w1, w0, v1, v0, ood_cur_ptr, rnd_ptr, ...] + movup.7 movup.4 sub + # => [v0 - p0, q1, q0, p1, w1, w0, v1, ood_cur_ptr, rnd_ptr, ...] + movup.6 + # => [v1, v0 - p0, q1, q0, p1, w1, w0, ood_cur_ptr, rnd_ptr, ...] + movup.6 movup.5 sub + # => [w0 - p1, v1, v0 - p0, q1, q0, w1, ood_cur_ptr, rnd_ptr, ...] + movup.5 + # => [w1, w0 - p1, v1, v0 - p0, q1, q0, ood_cur_ptr, rnd_ptr, ...] + padw dup.11 mem_loadw + # => [w1, w0 - p1, v1, v0 - p0, q1, q0, ood_cur_ptr, rnd_ptr, ...] + exec.mul_ext2_double + ext2add + # => [tmp1, tmp0, q1, q0, ood_cur_ptr, rnd_ptr, ...] + + # Compute the second and last two terms of the numerator + + padw movup.8 add.1 mem_loadw + # => [w1, w0, v1, v0, tmp1, tmp0, q1, q0, rnd_ptr, ...] + movup.3 movup.7 sub + # => [v0 - q0, w1, w0, v1, tmp1, tmp0, q1, rnd_ptr, ...] + movup.3 + # => [v1, v0 - q0, w1, w0, tmp1, tmp0, q1, rnd_ptr, ...] + movup.3 movup.6 sub + # => [w0 - q1, v1, v0 - q0, w1, tmp1, tmp0, rnd_ptr, ...] + movup.3 + # => [w1, w0 - q1, v1, v0 - q0, tmp1, tmp0, rnd_ptr, ...] + padw movup.10 add.1 mem_loadw + exec.mul_ext2_double + ext2add + # => [tmp'1, tmp'0, tmp1, tmp0, ...] + ext2add + # => [bnd_last1, bnd_last0, ...] +end + +#! Computes the subtraction of two tuples of extension field elements. +#! +#! Input: [q1, q0, p1, p0, w1, w0, v1, v0, ..] +#! Output: [g1, g0, f1, f0, ..] +#! +#! Cycles: 38 +export.subtract_ext2_double + movup.7 movup.7 movup.5 movup.5 + # => [p1, p0, v1, v0, q1, q0, w1, w0, ..] + ext2sub + # => [f1, f0, q1, q0, w1, w0, ..] + movdn.5 movdn.5 + # => [q1, q0, w1, w0, f1, f0, ..] + ext2sub + # => [g1, g0, f1, f0, ..] +end + +#! Loads two tuples of extension field elements, multiplies them and then sums them. +#! +#! The result is kept on the stack and the pointers are incremented. +#! +#! Input: [b_ptr, a_ptr, ...] +#! Output: [b_ptr + 1, a_ptr + 1, res1, res0, ...] +#! +#! Cycles: 45 +export.load_and_multiply_tuples_ext2 + # Load the first 2 elements of the ood frame + padw dup.4 add.1 swap.5 mem_loadw + # => [w1, w0, v1, v0, ood_cur_ptr, rnd_ptr, ...] + + # Load the first 2 random elements + padw dup.9 add.1 swap.10 mem_loadw + # => [b1, b0, a1, a0, w1, w0, v1, v0, ood_cur_ptr, rnd_ptr, ...] + + # Multiply each pair together + movup.7 movup.7 movup.5 movup.5 + # => [a1, a0, v1, v0, b1, b0, w1, w0, ood_cur_ptr, rnd_ptr, ...] + ext2mul + # => [tmp1, tmp0, b1, b0, w1, w0, ood_cur_ptr, rnd_ptr, ...] + movdn.5 movdn.5 + # => [b1, b0, w1, w0, tmp1, tmp0, ood_cur_ptr, rnd_ptr, ...] + ext2mul + + ext2add + # => [res1, res0, ood_cur_ptr, rnd_ptr, ...] + movdn.3 movdn.3 + # => [ood_cur_ptr, rnd_ptr, res1, res0, ...] +end + +#! Multiplies two tuples of extension field elements. +#! +#! Input: [b1, b0, a1, a0, w1, w0, v1, v0, ...] +#! Output: [t1, t0, s1, s0, ...] +#! +#! Cycles: 14 +export.mul_ext2_double + # Multiply each pair together + movup.7 movup.7 movup.5 movup.5 + # => [a1, a0, v1, v0, b1, b0, w1, w0, ...] + ext2mul + # => [s1, s0, b1, b0, w1, w0, ...] + movdn.5 movdn.5 + # => [b1, b0, w1, w0, s1, s0, ...] + ext2mul + # => [t1, t0, s1, s0, ...] +end + +#! Divides by the evaluation at the OOD point of the divisor of the boundary constraint against +#! the last row. +#! +#! Input: [z1, z0, bnd_last1, bnd_last0, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 15 +export.divide_boundary_last + swap exec.constants::minus_domain_gen_pow_7 add swap + ext2div +end + +#! Divides by the evaluation at the OOD point of the divisor of the boundary constraint against +#! the first row. +#! +#! Input: [z1, z0, bnd_first1, bnd_first0, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 15 +export.divide_boundary_first + swap exec.constants::minus_one add swap + ext2div +end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm b/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm index 66243ea47f..43f8f5d6fb 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm @@ -207,18 +207,16 @@ proc.load_query_row adv.push_mapval #=>[L, R, ptr, y, y, y, depth, index, query_ptr, ...] padw - # 26 felt + # 22 felt exec.constants::zero_word mem_loadw - drop push.2 swap.3 + drop push.6 swap.3 swapw.2 - repeat.3 + repeat.2 adv_pipe hperm end - - # TODO: Optimize by padding the leaf values so that we can use an adv_pipe - dropw adv_push.1 adv_push.1 push.0.0 + adv_loadw dup.12 mem_storew - swapw exec.constants::zero_word mem_loadw + swapw dropw adv_push.1 adv_push.1 push.0.0 dup.12 add.1 mem_storew hperm @@ -246,33 +244,6 @@ proc.load_query_row #=> [Y, Y, index, query_ptr, ...] end -#! Takes a query index and computes x := offset * domain_gen^index. It also computes the denominators -#! (x - z) and (x - gz). -#! -#! Input: [index, ...] -#! Output: [Z, x, index, ...] where Z := [-gz1, x -gz0, -z1, x - z0] -#! -#! Cycles: 57 -proc.compute_denominators - # Compute x = offset * domain_gen^index - exec.constants::lde_domain_generator dup.1 - exp.u32 - exec.constants::domain_offset mul - #=> [x, index, ...] - - padw - exec.constants::tmp10 mem_loadw - #=> [-z0, -gz0, -gz1, -z1, x, index, ...] - - # Compute Z := [-z1, x - z0, -gz1, x -gz0] - dup.4 add - #=> [x -z0, -gz0, -gz1, -z1, x, index, ...] - movdn.3 - #=> [-gz0, -gz1, -z1, x - z0, x, index, ...] - dup.4 add swap - #=> [-gz1, x -gz0, -z1, x - z0, x, index, ...] -end - #! Takes a query index and computes x := offset * domain_gen^index. It also computes the denominators #! (x - z) and (x - gz). #! @@ -280,8 +251,8 @@ end #! Output: [Z, Y, x, index, ...] where Z := [-gz1, x -gz0, -z1, x - z0] #! #! Cycles: 57 -proc.compute_denominators_new - exec.constants::tmp10 mem_loadw +proc.compute_denominators + exec.constants::tmp1 mem_loadw #=> [-z0, -gz0, -gz1, -z1, Y, index, ...] exec.constants::lde_domain_generator dup.9 @@ -311,7 +282,7 @@ end #! The procedure then outputs a stack in the same configuration but with the pointers and accumulators #! updated to [Y`, Y`, Acc`, P`, ...] where: #! -#! 1. P` := [CURRENT_TRACE_ROW_PTR+18, OOD_TRACE_PTR+70, DEEP_RAND_CC_PTR+70, 0]. +#! 1. P` := [CURRENT_TRACE_ROW_PTR+4, OOD_TRACE_PTR+12, DEEP_RAND_CC_PTR+12, 0]. #! 2. [Y`, Y`] is a "garbage" double-word used to later mem_stream auxiliary portion referenced now #! by CURRENT_TRACE_ROW_PTR`. #! 3. Acc` is the accumulator holding the updated numerator values i.e. with terms involving main @@ -333,42 +304,6 @@ proc.combine_main_trace_columns end end -#! Computes the random linear combination involving the aux trace columns and accumulates -#! into an accumulator. -#! More specifically, the procedure takes as input a stack in the following configuration: -#! [Y, Y, Acc, P, ...] where: -#! -#! 1. P := [CURRENT_TRACE_ROW_PTR, OOD_TRACE_PTR, DEEP_RAND_CC_PTR, 0]. -#! 2. [Y, Y] is a "garbage" double-word used to mem_stream data referenced by CURRENT_TRACE_ROW_PTR. -#! 3. Acc =: [Acc3, Acc2, Acc1, Acc0] is the accumulator holding the current numerator values. -#! -#! The procedure then outputs a stack in the same configuration but with the pointers and accumulators -#! updated to [Y`, Y`, Acc`, P`, ...] where: -#! -#! 1. P` := [CURRENT_TRACE_ROW_PTR+4, OOD_TRACE_PTR+7, DEEP_RAND_CC_PTR+7, 0]. -#! 2. [Y`, Y`] is a "garbage" double-word used to later mem_stream constraint composition polynomial -#! trace portion referenced now by CURRENT_TRACE_ROW_PTR`. -#! 3. Acc` is the accumulator holding the updated numerator values i.e. with terms involving main -#! trace columns included. -#! -#! Input: [Y, Y, Acc, P, ...] -#! Output: [Y`, Y`, Acc`, P`, ...] -#! -#! Cycles: 9 -proc.combine_aux_trace_columns - # Compute the random linear combination of the first 4 auxiliary trace columns - mem_stream - repeat.4 - exec.combine_aux - end - - # Compute the random linear combination of the last 3 auxiliary trace columns - mem_stream - repeat.3 - exec.combine_aux - end -end - #! Computes the random linear combination involving the constraint composition polynomial trace #! columns and accumulates into an accumulator. #! More specifically, the procedure takes as input a stack in the following configuration: @@ -395,17 +330,20 @@ proc.combine_constraint_poly_columns swapw.2 # Combine - repeat.3 + repeat.2 mem_stream repeat.4 exec.combine_aux end end + mem_stream + repeat.2 + exec.combine_aux + end # TODO: optimize this so as to keep the randomizer on the stack - mem_stream dropw - exec.constants::tmp9 mem_storew dropw + exec.constants::tmp4 mem_storew dropw #=> [Y, Y, Acc, P, ...] @@ -445,7 +383,8 @@ proc.divide_by_denominators_and_sum ext2add #=> [eval1, eval0, ...] - padw exec.constants::tmp9 mem_loadw drop drop + ## Add the randomizer + padw exec.constants::tmp4 mem_loadw drop drop #=> [r1, r0, eval1, eval0, ...] ext2add @@ -464,7 +403,7 @@ export.compute_deep_composition_polynomial_queries exec.constants::deep_rand_coef_ptr exec.constants::ood_trace_ptr exec.constants::current_trace_row_ptr - exec.constants::tmp11 mem_storew + exec.constants::tmp2 mem_storew #=>[X, query_ptr, query_end_ptr, ...] # Compute the negations of z and gz. @@ -481,7 +420,7 @@ export.compute_deep_composition_polynomial_queries #=> [-gz0, -z0, -gz1, -z1, ...] swap #=> [-z0, -gz0, -gz1, -z1, ...] - exec.constants::tmp10 mem_storew + exec.constants::tmp1 mem_storew #=>[X, query_ptr, query_end_ptr, ...] push.1 @@ -500,7 +439,7 @@ export.compute_deep_composition_polynomial_queries # Compute x := offset * domain_gen^index and denominators (x - z) and (x - gz) # # Cycles: 57 - exec.compute_denominators_new + exec.compute_denominators #=> [Z, Y, x, index, query_ptr, query_end_ptr, ...] where Z := [-gz1, x - gz0, -z1, x - z0] # III) @@ -513,7 +452,7 @@ export.compute_deep_composition_polynomial_queries ## a) Push pointers ## ## Cycles: 3 - swapw exec.constants::tmp11 mem_loadw + swapw exec.constants::tmp2 mem_loadw #=> [P, Z, x, index, query_ptr, query_end_ptr, ...] # where P := [CURRENT_TRACE_ROW_PTR, OOD_TRACE_PTR, DEEP_RAND_CC_PTR, 0] diff --git a/stdlib/asm/crypto/dsa/rpo_stark/mds_sbox.masm b/stdlib/asm/crypto/dsa/rpo_stark/mds_sbox.masm new file mode 100644 index 0000000000..65598d5601 --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/mds_sbox.masm @@ -0,0 +1,1304 @@ +use.std::crypto::dsa::rpo_stark::round_constants_polynomials +use.std::crypto::dsa::rpo_stark::permutation_constants + +#! Computes the result of the first matrix-vector multiplication of the state vector by the MDS +#! matrix, followed by component-wise addition of round constants and component-wise exponentiation +#! to the seventh power. +#! All of the operations happen over the quadratic extension field. +#! +#! Input: [state_ptr, out_ptr, z1, z0, ...] +#! Output: [...] +#! +#! Cycles: ~ 3420 +export.multiply_mds_add_constant_apply_sbox_round + dup + exec.multiply_mds_0_row + # => [state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 + exec.round_constants_polynomials::evaluate_ark1_index_0_at_z + ext2add + exec.sbox + # => [state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_1_row + # => [state1_1, state1_0, state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark1_index_1_at_z + ext2add + exec.sbox + # => [state1_1, state1_0, state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_2_row + # => [state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark1_index_2_at_z + ext2add + exec.sbox + # => [state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_3_row + # => [state3_1, state3_0, state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark1_index_3_at_z + ext2add + exec.sbox + # => [state3_1, state3_0, state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.1 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_4_row + # => [state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark1_index_4_at_z + ext2add + exec.sbox + # => [state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_5_row + # => [state5_1, state5_0, state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark1_index_5_at_z ext2add + exec.sbox + # => [state5_1, state5_0, state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.2 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + + dup + exec.multiply_mds_6_row + # => [state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark1_index_6_at_z + ext2add + exec.sbox + # => [state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_7_row + # => [state7_1, state7_0, state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark1_index_7_at_z ext2add + exec.sbox + # => [state7_1, state7_0, state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.3 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_8_row + # => [state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark1_index_8_at_z + ext2add + exec.sbox + # => [state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_9_row + # => [state9_1, state9_0, state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark1_index_9_at_z ext2add + exec.sbox + # => [state9_1, state9_0, state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.4 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_10_row + # => [state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark1_index_10_at_z + ext2add + exec.sbox + # => [state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_11_row + # => [state11_1, state11_0, state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark1_index_11_at_z ext2add + exec.sbox + # => [state11_1, state11_0, state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.5 mem_storew dropw dropw + # => [state_ptr, out_ptr, z1, z0, ...] +end + +#! Computes the result of the second matrix-vector multiplication of the state vector by the MDS +#! matrix followed by component-wise addition of round constants. +#! All of the operations happen over the quadratic extension field. +#! +#! Input: [state_ptr, out_ptr, z1, z0, ...] +#! Output: [...] +#! +#! Cycles: 3156 +export.multiply_mds_add_constant + dup + exec.multiply_mds_0_row + # => [state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark2_index_0_at_z + ext2add + # => [state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_1_row + # => [state1_1, state1_0, state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark2_index_1_at_z + ext2add + # => [state1_1, state1_0, state0_1, state0_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_2_row + # => [state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark2_index_2_at_z + ext2add + # => [state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_3_row + # => [state3_1, state3_0, state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark2_index_3_at_z + ext2add + # => [state3_1, state3_0, state2_1, state2_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.1 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_4_row + # => [state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark2_index_4_at_z + ext2add + # => [state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_5_row + # => [state5_1, state5_0, state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark2_index_5_at_z + ext2add + # => [state5_1, state5_0, state4_1, state4_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.2 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + + dup + exec.multiply_mds_6_row + # => [state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark2_index_6_at_z + ext2add + # => [state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_7_row + # => [state7_1, state7_0, state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark2_index_7_at_z + ext2add + # => [state7_1, state7_0, state6_1, state6_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.3 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_8_row + # => [state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark2_index_8_at_z + ext2add + # => [state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_9_row + # => [state9_1, state9_0, state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark2_index_9_at_z + ext2add + # => [state9_1, state9_0, state8_1, state8_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.4 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dup + exec.multiply_mds_10_row + # => [state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + dup.5 dup.5 exec.round_constants_polynomials::evaluate_ark2_index_10_at_z + ext2add + # => [state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + + dup.2 + exec.multiply_mds_11_row + # => [state11_1, state11_0, state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + dup.7 dup.7 exec.round_constants_polynomials::evaluate_ark2_index_11_at_z + ext2add + # => [state11_1, state11_0, state10_1, state10_0, state_ptr, out_ptr, z1, z0, ...] + + dup.5 add.5 mem_storew dropw + # => [state_ptr, out_ptr, z1, z0, ...] + + dropw +end + +#! Computes the sbox in the backward direction and outputs the final random linear combination +#! of all transitional constraints. +#! +#! Input: [nxt_ptr, fwd_ptr, rnd_ptr, ...] +#! Output: [val1, val0, ...] +#! +#! Cycles: 685 +export.sbox_next_and_compute_random_linear_combination + + repeat.6 + # 1) Compute the sbox on the next state + padw dup.4 mem_loadw + #=> [t1_1, t1_0, t0_1, t0_0, nxt_ptr, fwd_ptr, rnd_ptr, ...] + + exec.sbox_double + #=> [t1_1, t1_0, t0_1, t0_0, nxt_ptr, fwd_ptr, rnd_ptr, ...] + + # 2) Compute the difference between forward and backward + + padw dup.9 mem_loadw + #=> [s1_1, s1_0, s0_1, s0_0, t1_1, t1_0, t0_1, t0_0, nxt_ptr, fwd_ptr, rnd_ptr, ...] + + exec.compute_difference_double + #=> [d1_1, d1_0, d0_1, d0_0, nxt_ptr, fwd_ptr, rnd_ptr, ...] + + # 3) Multiply with randomness + + padw dup.10 mem_loadw + #=> [r1_1, r1_0, r0_1, r0_0, d1_1, d1_0, d0_1, d0_0, nxt_ptr, fwd_ptr, rnd_ptr, ...] + + + exec.multiply_extension_double + #=> [a1_1, a1_0, a0_1, a0_0, nxt_ptr, fwd_ptr, rnd_ptr, ...] + + # 4) Sum the two values + ext2add + #=> [a1, a0, nxt_ptr, fwd_ptr, rnd_ptr, ...] + + # 5) Update pointers and prepare for next iteration + repeat.3 + movup.4 add.1 + end + #=> [nxt_ptr, fwd_ptr, rnd_ptr, a1, a0, ...] + end + + drop drop drop + + repeat.5 + ext2add + end + #=> [val1, val0, ...] + +end + +# MDS MATRIX MULTIPLICATION PROCEDURES +# ================================================================================================= + +#! Computes coordinate 0 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_0_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_0_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_0_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_0_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_0_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_0_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_0_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 1 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_1_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_1_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_1_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_1_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_1_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_1_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_1_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 2 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_2_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_2_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_2_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_2_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_2_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_2_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_2_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 3 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_3_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_3_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_3_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_3_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_3_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_3_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_3_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 4 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_4_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_4_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_4_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_4_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_4_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_4_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_4_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 5 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_5_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_5_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_5_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_5_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_5_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_5_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_5_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 6 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_6_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_6_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_6_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_6_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_6_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_6_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_6_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 7 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_7_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_7_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_7_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_7_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_7_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_7_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_7_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 8 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_8_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_8_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_8_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_8_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_8_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_8_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_8_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 9 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_9_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_9_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_9_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_9_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_9_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_9_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_9_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 10 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_10_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_10_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_10_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_10_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_10_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_10_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_10_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + +#! Computes coordinate 11 of the result of the MDS multiplication. +#! +#! Input: [state_ptr, ...] +#! Output: [res1, res0, ...] +#! +#! Cycles: 190 +export.multiply_mds_11_row + + # load the first set of 2 state elements + padw dup.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + + # multiply with the first 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_11_first_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, state_ptr, ...] + exec.multiply_double_extension_by_base + # => [acc1, acc0, state_ptr, ...] + + # load the second set of 2 state elements + padw dup.6 add.1 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the second 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_11_second_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the third set of 2 state elements + padw dup.6 add.2 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the third 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_11_third_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fourth set of 2 state elements + padw dup.6 add.3 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fourth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_11_fourth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the fifth set of 2 state elements + padw dup.6 add.4 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + + # multiply with the fifth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_11_fifth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, state_ptr, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, state_ptr, ...] + + # load the sixth set of 2 state elements + padw movup.6 add.5 mem_loadw + # => [s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + + # multiply with the sixth 2 elements of the current row of the MDS matrix + exec.permutation_constants::get_mds_row_11_sixth_tuple + # => [k1, k0, s1_1, s1_0, s0_1, s0_0, acc1, acc0, ...] + exec.multiply_double_extension_by_base + ext2add + # => [acc1, acc0, ...] +end + + +# FIELD ARITHMETIC HELPER FUNCTIONS +# ================================================================================================= + +#! Multiplies a tuple of quadratic extension field elements by a tuple of base field elements. +#! +#! Input: [k1, k0, s1_1, s1_0, s0_1, s0_0, ...] +#! Output: [res1, res0, ...] where res = (res1, res0) = s0 * k0 + s1 * k1 and sj = (sj_0, sj_1) are +#! two elements in the quadratic extension field for j = 0, 1. +#! +#! Cycles: 17 +export.multiply_double_extension_by_base + dup movup.4 mul + # => [s1_0 * k1, k1, k0, s1_1, s0_1, s0_0, ...] + + swap movup.3 mul + # => [s1_1 * k1, s1_0 * k1, k0, s0_1, s0_0, ...] + + dup.2 movup.4 mul add + # => [res1, s1_0 * k1, k0, s0_0, ...] where res1 = s0_1 * k0 + s1_1 * k1 + + swap.2 movup.3 mul add + # => [res0, res1, ...] where res0 = s0_0 * k0 + s1_0 * k1 + + swap + # => [res1, res0, ...] +end + +#! Computes the sbox map on an element in the quadratic extension field. +#! +#! Input: [x1, x0, ...] +#! Output: [y1, y0, ...] where y = x^7 in the quadratic extension field. +#! +#! Cycles: 24 +export.sbox + dup.1 dup.1 + # => [x1, x0, x1, x0, ...] + + dup.1 dup.1 ext2mul + # => [xsq1, xsq0, x1, x0, ...] + + dup.1 dup.1 dup.1 dup.1 + # => [xsq1, xsq0, xsq1, xsq0, xsq1, xsq0, x1, x0, ...] + + ext2mul + # => [xquad1, xquad0, xsq1, xsq0, x1, x0, ...] + + movdn.5 movdn.5 + # => [xsq1, xsq0, x1, x0, xquad1, xquad0, ...] + + ext2mul + # => [xcub1, xcub0, xquad1, xquad0, ...] + + ext2mul + # => [y1, y0, ...] +end + +#! Computes the sbox map on tuple of elements in the quadratic extension field. +#! +#! Input: [y1, y0, x1, x0, ...] +#! Output: [w1, w0, v1, v0, ...] where v = x^7 and w = y^7 in the quadratic extension field. +#! +#! Cycles: 52 +export.sbox_double + movup.3 movup.3 + exec.sbox + movup.3 movup.3 + exec.sbox +end + + +#! Subtracts two pairs of elements in the quadratic extension field. +#! +#! Input: [s1_1, s1_0, s0_1, s0_0, t1_1, t1_0, t0_1, t0_0, ...] +#! Output: [d1_1, d1_0, d0_1, d0_0, ...] +#! +#! where: +#! - d0 = t0 - s0. +#! - d1 = t1 - s1. +#! +#! Cycles: 24 +proc.compute_difference_double + # 1) Compute d0 + movup.7 movup.4 neg add + # => [t0_0 - s0_0, s1_1, s1_0, s0_1, t1_1, t1_0, t0_1, ...] + movup.6 movup.4 neg add + # => [t0_1 - s0_1, t0_0 - s0_0, s1_1, s1_0, t1_1, t1_0, ...] + + # 2) Compute d1 + movup.5 movup.4 neg add + # => [t1_0 - s1_0, t0_1 - s0_1, t0_0 - s0_0, s1_1, t1_1, ...] + movup.4 movup.4 neg add + # => [s1_1, t1_1, t1_0 - s1_0, t0_1 - s0_1, t0_0 - s0_0, ...] +end + +#! Multiplies two pairs of elements in the quadratic extension field. +#! +#! Input: [s1_1, s1_0, s0_1, s0_0, t1_1, t1_0, t0_1, t0_0, ...] +#! Output: [d1_1, d1_0, d0_1, d0_0, ...] +#! +#! where: +#! - d0 = t0 * s0. +#! - d1 = t1 * s1. +#! +#! Cycles: 18 +proc.multiply_extension_double + # 1) Compute d0 + movup.7 movup.7 movup.5 movup.5 + # => [s0_1, s0_0, t0_1, t0_0, s1_1, s1_0, t1_1, t1_0, ...] + ext2mul + # => [d0_1, d0_0, s1_1, s1_0, t1_1, t1_0, ...] + + # 2) Compute d1 + movdn.5 movdn.5 + # => [s1_1, s1_0, t1_1, t1_0, d0_1, d0_0, ...] + ext2mul + # => [d1_1, d1_0, d0_1, d0_0, ...] +end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm b/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm index 567b086507..7372e3561e 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/ood_frames.masm @@ -16,8 +16,7 @@ export.load_evaluation_frame # current row and a1 from the next row. exec.constants::ood_trace_ptr - push.0.0.0.0 - padw padw + padw padw padw repeat.6 adv_pipe hperm @@ -30,6 +29,7 @@ export.load_evaluation_frame drop end + #! Loads OOD constraint composition polynomial evaluation columns into memory and reseeds the random #! coin. #! @@ -44,7 +44,7 @@ export.load_constraint_evaluations # the values in memory as [v0, v1, 0, 0] where v := (v0, v1) ranges over the 8 values `value_i`. # Load value_0 and value_1 - padw + push.4.0.0.0 padw adv_loadw dup.3 dup.3 push.0.0 @@ -104,108 +104,123 @@ export.load_constraint_evaluations mem_storew dropw + # Load value_10 dup.1 dup.1 push.0.0 exec.constants::ood_constraint_evals_ptr add.9 mem_storew dropw - swapw + swapw dropw + padw + hperm + + exec.rpo::squeeze_digest +end - # Load value_10 and value_11 +#! Loads OOD constraint composition polynomial evaluation columns into memory and reseeds the random +#! coin. +#! +#! Input: [...] +#! Output: [EVAL_HASH, ...] +#! Cycles: 160 +export.load_constraint_evaluations_old + # Read OOD constraint evaluations. These are 8 ExtFelt `value_i` such that the value of the + # constraint evaluation polynomial at `z` `H(z)` equals `\sum_0^7 z^(N * i) value_i` where N + # is the execution trace length. + # In order to facilitate the computation of the DEEP composition polynomial queries, we lay out + # the values in memory as [v0, v1, 0, 0] where v := (v0, v1) ranges over the 8 values `value_i`. + + # Load value_0 and value_1 + padw + padw adv_loadw dup.3 dup.3 push.0.0 - exec.constants::ood_constraint_evals_ptr add.10 - mem_storew + exec.constants::ood_constraint_evals_ptr mem_storew dropw dup.1 dup.1 push.0.0 - exec.constants::ood_constraint_evals_ptr add.11 + exec.constants::ood_constraint_evals_ptr add.1 + mem_storew + + # Load value_2 and value_3 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.2 mem_storew dropw + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.3 + mem_storew + + dropw hperm - - exec.rpo::squeeze_digest -end -#! Computes the H(z) evaluation of the constraint composition polynomial at the OOD element z. -#! -#! Input: [...] -#! Output: [res1, res0, ...] -#! Cycles: 155 -export.compute_Hz_old - # Load the pointer to the OOD constraint polynomials evaluations - exec.constants::ood_constraint_evals_ptr - # => [ptr, ...] - - # Compute `H(z)` - ## Load `value_i`'s - - # Load value_0 - padw dup.4 mem_loadw - # => [0, 0, v0_1, v0_0, ptr, ...] - - # Load value_1 - push.0.0 dup.6 add.1 mem_loadw - # => [0, 0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + # Load value_4 and value_5 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.4 + mem_storew + dropw - # Load value_2 - push.0.0 dup.8 add.2 mem_loadw - # => [0, 0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.5 + mem_storew + dropw - # Load value_3 - push.0.0 dup.10 add.3 mem_loadw - # => [0, 0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + swapw - # Load value_4 - push.0.0 dup.12 add.4 mem_loadw - # => [0, 0, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + # Load value_6 and value_7 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.6 + mem_storew + dropw + + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.7 + mem_storew + dropw - # Load value_5 - push.0.0 movup.14 movdn.4 dup.4 add.5 mem_loadw - # => [0, 0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + hperm - # Load value_6 - push.0.0 dup.6 add.6 mem_loadw - # => [0, 0, v6_1, v6_0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + # Load value_8 and value_9 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.8 + mem_storew + dropw - # Load value_7 - push.0.0 movup.8 add.7 mem_loadw - # => [0, 0, v7_1, v7_0, v6_1, v6_0, v5_1, v5_0, ptr, v4_1, v4_0, v3_1, v3_0, v2_1, v2_0, v1_1, v1_0, v0_1, v0_0, ptr, ...] + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.9 + mem_storew + dropw - ## Load z^N where N is the length of the execution trace - push.0.0 - exec.constants::z_ptr mem_loadw - movup.2 drop - movup.2 drop - # => [z1, z0, value_7, ... ,value_0] + swapw - # Horner evaluation - # TODO: maybe can be done faster in another way - repeat.6 - dup - movdn.6 - dup.1 - movdn.7 - # => [z1, z0, value_7, value_6, z1, z0, value_5, ... ,value_0] + # Load value_10 and value_11 + adv_loadw + dup.3 dup.3 push.0.0 + exec.constants::ood_constraint_evals_ptr add.10 + mem_storew + dropw - ext2mul - ext2add - # => [acc1, acc0, z1, z0, value_5, ... ,value_0] + dup.1 dup.1 push.0.0 + exec.constants::ood_constraint_evals_ptr add.11 + mem_storew + dropw - movup.3 - movup.3 - # => [z1, z0, acc1, acc0, value_5, ... ,value_0] - end - ext2mul - ext2add + hperm + + exec.rpo::squeeze_digest end #! Computes the H(z) evaluation of the constraint composition polynomial at the OOD element z. #! #! Input: [coef_ptr, x1, x0, ...] #! Output: [res1, res0, ...] -#! Cycles: 155 +#! +#! Cycles: 270 export.compute_Hz exec.constants::ood_constraint_evals_ptr add.11 movdn.2 diff --git a/stdlib/asm/crypto/dsa/rpo_stark/permutation_constants.masm b/stdlib/asm/crypto/dsa/rpo_stark/permutation_constants.masm new file mode 100644 index 0000000000..ee10960fad --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/permutation_constants.masm @@ -0,0 +1,1292 @@ + +# MDS MATRIX CONSTANTS +# ================================================================================================= + +const.MDS_0=7 +const.MDS_1=23 +const.MDS_2=8 +const.MDS_3=26 +const.MDS_4=13 +const.MDS_5=10 +const.MDS_6=9 +const.MDS_7=7 +const.MDS_8=6 +const.MDS_9=22 +const.MDS_10=21 +const.MDS_11=8 + +# First row + +export.get_mds_row_0_first_tuple + push.MDS_0 push.MDS_1 +end + +export.get_mds_row_0_second_tuple + push.MDS_2 push.MDS_3 +end + +export.get_mds_row_0_third_tuple + push.MDS_4 push.MDS_5 +end + +export.get_mds_row_0_fourth_tuple + push.MDS_6 push.MDS_7 +end + +export.get_mds_row_0_fifth_tuple + push.MDS_8 push.MDS_9 +end + +export.get_mds_row_0_sixth_tuple + push.MDS_10 push.MDS_11 +end + +# Second row + +export.get_mds_row_1_first_tuple + push.MDS_11 push.MDS_0 +end + +export.get_mds_row_1_second_tuple + push.MDS_1 push.MDS_2 +end + +export.get_mds_row_1_third_tuple + push.MDS_3 push.MDS_4 +end + +export.get_mds_row_1_fourth_tuple + push.MDS_5 push.MDS_6 +end + +export.get_mds_row_1_fifth_tuple + push.MDS_7 push.MDS_8 +end + +export.get_mds_row_1_sixth_tuple + push.MDS_9 push.MDS_10 +end + +# Third row + +export.get_mds_row_2_first_tuple + push.MDS_10 push.MDS_11 +end + +export.get_mds_row_2_second_tuple + push.MDS_0 push.MDS_1 +end + +export.get_mds_row_2_third_tuple + push.MDS_2 push.MDS_3 +end + +export.get_mds_row_2_fourth_tuple + push.MDS_4 push.MDS_5 +end + +export.get_mds_row_2_fifth_tuple + push.MDS_6 push.MDS_7 +end + +export.get_mds_row_2_sixth_tuple + push.MDS_8 push.MDS_9 +end + +# Fourth row + +export.get_mds_row_3_first_tuple + push.MDS_9 push.MDS_10 +end + +export.get_mds_row_3_second_tuple + push.MDS_11 push.MDS_0 +end + +export.get_mds_row_3_third_tuple + push.MDS_1 push.MDS_2 +end + +export.get_mds_row_3_fourth_tuple + push.MDS_3 push.MDS_4 +end + +export.get_mds_row_3_fifth_tuple + push.MDS_5 push.MDS_6 +end + +export.get_mds_row_3_sixth_tuple + push.MDS_7 push.MDS_8 +end + +# Fifth row + +export.get_mds_row_4_first_tuple + push.MDS_8 push.MDS_9 +end + +export.get_mds_row_4_second_tuple + push.MDS_10 push.MDS_11 +end + +export.get_mds_row_4_third_tuple + push.MDS_0 push.MDS_1 +end + +export.get_mds_row_4_fourth_tuple + push.MDS_2 push.MDS_3 +end + +export.get_mds_row_4_fifth_tuple + push.MDS_4 push.MDS_5 +end + +export.get_mds_row_4_sixth_tuple + push.MDS_6 push.MDS_7 +end + +# Sixth row + +export.get_mds_row_5_first_tuple + push.MDS_7 push.MDS_8 +end + +export.get_mds_row_5_second_tuple + push.MDS_9 push.MDS_10 +end + +export.get_mds_row_5_third_tuple + push.MDS_11 push.MDS_0 +end + +export.get_mds_row_5_fourth_tuple + push.MDS_1 push.MDS_2 +end + +export.get_mds_row_5_fifth_tuple + push.MDS_3 push.MDS_4 +end + +export.get_mds_row_5_sixth_tuple + push.MDS_5 push.MDS_6 +end + +# Seventh row + +export.get_mds_row_6_first_tuple + push.MDS_6 push.MDS_7 +end + +export.get_mds_row_6_second_tuple + push.MDS_8 push.MDS_9 +end + +export.get_mds_row_6_third_tuple + push.MDS_10 push.MDS_11 +end + +export.get_mds_row_6_fourth_tuple + push.MDS_0 push.MDS_1 +end + +export.get_mds_row_6_fifth_tuple + push.MDS_2 push.MDS_3 +end + +export.get_mds_row_6_sixth_tuple + push.MDS_4 push.MDS_5 +end + +# Eight row + +export.get_mds_row_7_first_tuple + push.MDS_5 push.MDS_6 +end + +export.get_mds_row_7_second_tuple + push.MDS_7 push.MDS_8 +end + +export.get_mds_row_7_third_tuple + push.MDS_9 push.MDS_10 +end + +export.get_mds_row_7_fourth_tuple + push.MDS_11 push.MDS_0 +end + +export.get_mds_row_7_fifth_tuple + push.MDS_1 push.MDS_2 +end + +export.get_mds_row_7_sixth_tuple + push.MDS_3 push.MDS_4 +end + +# Ninth row + +export.get_mds_row_8_first_tuple + push.MDS_4 push.MDS_5 +end + +export.get_mds_row_8_second_tuple + push.MDS_6 push.MDS_7 +end + +export.get_mds_row_8_third_tuple + push.MDS_8 push.MDS_9 +end + +export.get_mds_row_8_fourth_tuple + push.MDS_10 push.MDS_11 +end + +export.get_mds_row_8_fifth_tuple + push.MDS_0 push.MDS_1 +end + +export.get_mds_row_8_sixth_tuple + push.MDS_2 push.MDS_3 +end + +# Tenth row + +export.get_mds_row_9_first_tuple + push.MDS_3 push.MDS_4 +end + +export.get_mds_row_9_second_tuple + push.MDS_5 push.MDS_6 +end + +export.get_mds_row_9_third_tuple + push.MDS_7 push.MDS_8 +end + +export.get_mds_row_9_fourth_tuple + push.MDS_9 push.MDS_10 +end + +export.get_mds_row_9_fifth_tuple + push.MDS_11 push.MDS_0 +end + +export.get_mds_row_9_sixth_tuple + push.MDS_1 push.MDS_2 +end + +# Eleventh row + +export.get_mds_row_10_first_tuple + push.MDS_2 push.MDS_3 +end + +export.get_mds_row_10_second_tuple + push.MDS_4 push.MDS_5 +end + +export.get_mds_row_10_third_tuple + push.MDS_6 push.MDS_7 +end + +export.get_mds_row_10_fourth_tuple + push.MDS_8 push.MDS_9 +end + +export.get_mds_row_10_fifth_tuple + push.MDS_10 push.MDS_11 +end + +export.get_mds_row_10_sixth_tuple + push.MDS_0 push.MDS_1 +end + +# Twelvth row + +export.get_mds_row_11_first_tuple + push.MDS_1 push.MDS_2 +end + +export.get_mds_row_11_second_tuple + push.MDS_3 push.MDS_4 +end + +export.get_mds_row_11_third_tuple + push.MDS_5 push.MDS_6 +end + +export.get_mds_row_11_fourth_tuple + push.MDS_7 push.MDS_8 +end + +export.get_mds_row_11_fifth_tuple + push.MDS_9 push.MDS_10 +end + +export.get_mds_row_11_sixth_tuple + push.MDS_11 push.MDS_0 +end + + +# ROUND CONSTANTS INTERPOLATING POLYNOMIALS COEFFICIENTS +# ================================================================================================= + + +export.get_ark1_index_0_poly_coef_0 + push.11161339744919841557 +end + + +export.get_ark1_index_0_poly_coef_1 + push.13524602409635810170 +end + + +export.get_ark1_index_0_poly_coef_2 + push.9922086147590952635 +end + + +export.get_ark1_index_0_poly_coef_3 + push.17016545619512577097 +end + + +export.get_ark1_index_0_poly_coef_4 + push.2418654603508424991 +end + + +export.get_ark1_index_0_poly_coef_5 + push.10286692761237010417 +end + + +export.get_ark1_index_0_poly_coef_6 + push.283349644643922063 +end + + +export.get_ark1_index_0_poly_coef_7 + push.14963467652898065746 +end + + +export.get_ark1_index_1_poly_coef_0 + push.4396886864075565886 +end + + +export.get_ark1_index_1_poly_coef_1 + push.14421256556794208365 +end + + +export.get_ark1_index_1_poly_coef_2 + push.17618762504959858245 +end + + +export.get_ark1_index_1_poly_coef_3 + push.16500226033358169876 +end + + +export.get_ark1_index_1_poly_coef_4 + push.9022700061563201986 +end + + +export.get_ark1_index_1_poly_coef_5 + push.8797682842773526496 +end + + +export.get_ark1_index_1_poly_coef_6 + push.1406606624688743502 +end + + +export.get_ark1_index_1_poly_coef_7 + push.8145419553858764711 +end + + +export.get_ark1_index_2_poly_coef_0 + push.12771104083879797304 +end + + +export.get_ark1_index_2_poly_coef_1 + push.4384096284379081589 +end + + +export.get_ark1_index_2_poly_coef_2 + push.10611032300457160935 +end + + +export.get_ark1_index_2_poly_coef_3 + push.14994324994142571878 +end + + +export.get_ark1_index_2_poly_coef_4 + push.9653495130142868572 +end + + +export.get_ark1_index_2_poly_coef_5 + push.1050988870128088335 +end + + +export.get_ark1_index_2_poly_coef_6 + push.17560352664313181270 +end + + +export.get_ark1_index_2_poly_coef_7 + push.2124731360259211283 +end + + +export.get_ark1_index_3_poly_coef_0 + push.918334021027209062 +end + + +export.get_ark1_index_3_poly_coef_1 + push.10152047439645494196 +end + + +export.get_ark1_index_3_poly_coef_2 + push.214997880704220386 +end + + +export.get_ark1_index_3_poly_coef_3 + push.6569423833286224818 +end + + +export.get_ark1_index_3_poly_coef_4 + push.533558171595040129 +end + + +export.get_ark1_index_3_poly_coef_5 + push.1280997866548339118 +end + + +export.get_ark1_index_3_poly_coef_6 + push.12874339497899932877 +end + + +export.get_ark1_index_3_poly_coef_7 + push.4456934672112444564 +end + + +export.get_ark1_index_4_poly_coef_0 + push.11692764253303674470 +end + + +export.get_ark1_index_4_poly_coef_1 + push.515284590742120187 +end + + +export.get_ark1_index_4_poly_coef_2 + push.17292488966298323792 +end + + +export.get_ark1_index_4_poly_coef_3 + push.10844018419856250332 +end + + +export.get_ark1_index_4_poly_coef_4 + push.18023781777216126430 +end + + +export.get_ark1_index_4_poly_coef_5 + push.13673939141435367318 +end + + +export.get_ark1_index_4_poly_coef_6 + push.6234658754536564709 +end + + +export.get_ark1_index_4_poly_coef_7 + push.1899018416707427428 +end + + +export.get_ark1_index_5_poly_coef_0 + push.4346339672760616239 +end + + +export.get_ark1_index_5_poly_coef_1 + push.8455287875953668445 +end + + +export.get_ark1_index_5_poly_coef_2 + push.7797109022092361792 +end + + +export.get_ark1_index_5_poly_coef_3 + push.3185550689235771247 +end + + +export.get_ark1_index_5_poly_coef_4 + push.17857685726367183274 +end + + +export.get_ark1_index_5_poly_coef_5 + push.1222554742061216844 +end + + +export.get_ark1_index_5_poly_coef_6 + push.14357877464027708054 +end + + +export.get_ark1_index_5_poly_coef_7 + push.13961894750151243783 +end + + +export.get_ark1_index_6_poly_coef_0 + push.12338144193459599473 +end + + +export.get_ark1_index_6_poly_coef_1 + push.4787262909192723447 +end + + +export.get_ark1_index_6_poly_coef_2 + push.18009332799257726044 +end + + +export.get_ark1_index_6_poly_coef_3 + push.1520757922292500220 +end + + +export.get_ark1_index_6_poly_coef_4 + push.3425116756870399082 +end + + +export.get_ark1_index_6_poly_coef_5 + push.82309007773463393 +end + + +export.get_ark1_index_6_poly_coef_6 + push.10999213665537908638 +end + + +export.get_ark1_index_6_poly_coef_7 + push.14153095467414650905 +end + + +export.get_ark1_index_7_poly_coef_0 + push.17721191843366953765 +end + + +export.get_ark1_index_7_poly_coef_1 + push.2981247010710770409 +end + + +export.get_ark1_index_7_poly_coef_2 + push.2629404272561006980 +end + + +export.get_ark1_index_7_poly_coef_3 + push.17998360743101617303 +end + + +export.get_ark1_index_7_poly_coef_4 + push.9696450523361047127 +end + + +export.get_ark1_index_7_poly_coef_5 + push.2820580057022838499 +end + + +export.get_ark1_index_7_poly_coef_6 + push.17030972937639676955 +end + + +export.get_ark1_index_7_poly_coef_7 + push.6253753013662739610 +end + + +export.get_ark1_index_8_poly_coef_0 + push.13086121874681361472 +end + + +export.get_ark1_index_8_poly_coef_1 + push.18420464834339013679 +end + + +export.get_ark1_index_8_poly_coef_2 + push.4941115579440263820 +end + + +export.get_ark1_index_8_poly_coef_3 + push.1400604787004895902 +end + + +export.get_ark1_index_8_poly_coef_4 + push.5744512854726105972 +end + + +export.get_ark1_index_8_poly_coef_5 + push.1832983366606572285 +end + + +export.get_ark1_index_8_poly_coef_6 + push.18156162340052117729 +end + + +export.get_ark1_index_8_poly_coef_7 + push.1717456198050769295 +end + + +export.get_ark1_index_9_poly_coef_0 + push.13529699806230160963 +end + + +export.get_ark1_index_9_poly_coef_1 + push.10237180984848504073 +end + + +export.get_ark1_index_9_poly_coef_2 + push.10148251122167516761 +end + + +export.get_ark1_index_9_poly_coef_3 + push.5675543704421645935 +end + + +export.get_ark1_index_9_poly_coef_4 + push.3100011361405407410 +end + + +export.get_ark1_index_9_poly_coef_5 + push.10203341767187748478 +end + + +export.get_ark1_index_9_poly_coef_6 + push.1728635344260683954 +end + + +export.get_ark1_index_9_poly_coef_7 + push.13678341586485649054 +end + + +export.get_ark1_index_10_poly_coef_0 + push.6968853056426555231 +end + + +export.get_ark1_index_10_poly_coef_1 + push.12773799811074245642 +end + + +export.get_ark1_index_10_poly_coef_2 + push.7576847717756774592 +end + + +export.get_ark1_index_10_poly_coef_3 + push.6366612445863536555 +end + + +export.get_ark1_index_10_poly_coef_4 + push.1978027386177818117 +end + + +export.get_ark1_index_10_poly_coef_5 + push.11053027413584437217 +end + + +export.get_ark1_index_10_poly_coef_6 + push.17425383571650433644 +end + + +export.get_ark1_index_10_poly_coef_7 + push.800595103462440440 +end + + +export.get_ark1_index_11_poly_coef_0 + push.8239981436827461892 +end + + +export.get_ark1_index_11_poly_coef_1 + push.3056366513263287059 +end + + +export.get_ark1_index_11_poly_coef_2 + push.1477273142604874244 +end + + +export.get_ark1_index_11_poly_coef_3 + push.6179499463670119678 +end + + +export.get_ark1_index_11_poly_coef_4 + push.697057001204997696 +end + + +export.get_ark1_index_11_poly_coef_5 + push.3315366854959170049 +end + + +export.get_ark1_index_11_poly_coef_6 + push.10854693463399578271 +end + + +export.get_ark1_index_11_poly_coef_7 + push.1284048563685561340 +end + + +export.get_ark2_index_0_poly_coef_0 + push.17541136370002042541 +end + + +export.get_ark2_index_0_poly_coef_1 + push.9207305567328033659 +end + + +export.get_ark2_index_0_poly_coef_2 + push.5302649368994107543 +end + + +export.get_ark2_index_0_poly_coef_3 + push.9295148820033412177 +end + + +export.get_ark2_index_0_poly_coef_4 + push.10458889936493236127 +end + + +export.get_ark2_index_0_poly_coef_5 + push.9250400196904370803 +end + + +export.get_ark2_index_0_poly_coef_6 + push.10120490625039566031 +end + + +export.get_ark2_index_0_poly_coef_7 + push.8688018155220772690 +end + + +export.get_ark2_index_1_poly_coef_0 + push.12290374148348092865 +end + + +export.get_ark2_index_1_poly_coef_1 + push.7598939068586646899 +end + + +export.get_ark2_index_1_poly_coef_2 + push.5676794387987529535 +end + + +export.get_ark2_index_1_poly_coef_3 + push.1808022546556847354 +end + + +export.get_ark2_index_1_poly_coef_4 + push.17375499837810978191 +end + + +export.get_ark2_index_1_poly_coef_5 + push.3553069938644104544 +end + + +export.get_ark2_index_1_poly_coef_6 + push.16222342997907433812 +end + + +export.get_ark2_index_1_poly_coef_7 + push.6092809452904130954 +end + + +export.get_ark2_index_2_poly_coef_0 + push.6330834748146988998 +end + + +export.get_ark2_index_2_poly_coef_1 + push.18232818846548175240 +end + + +export.get_ark2_index_2_poly_coef_2 + push.16738194939201375332 +end + + +export.get_ark2_index_2_poly_coef_3 + push.12422045225973843477 +end + + +export.get_ark2_index_2_poly_coef_4 + push.2649532336751053336 +end + + +export.get_ark2_index_2_poly_coef_5 + push.9144083707269204039 +end + + +export.get_ark2_index_2_poly_coef_6 + push.12856846028102044258 +end + + +export.get_ark2_index_2_poly_coef_7 + push.771358571379849309 +end + + +export.get_ark2_index_3_poly_coef_0 + push.6068602067966145177 +end + + +export.get_ark2_index_3_poly_coef_1 + push.5255602161993055124 +end + + +export.get_ark2_index_3_poly_coef_2 + push.16592542373283749979 +end + + +export.get_ark2_index_3_poly_coef_3 + push.13453764978722298280 +end + + +export.get_ark2_index_3_poly_coef_4 + push.2813161176846149028 +end + + +export.get_ark2_index_3_poly_coef_5 + push.13008840161409309674 +end + + +export.get_ark2_index_3_poly_coef_6 + push.12882021675720283520 +end + + +export.get_ark2_index_3_poly_coef_7 + push.17945725469014942220 +end + + +export.get_ark2_index_4_poly_coef_0 + push.1116014701074041230 +end + + +export.get_ark2_index_4_poly_coef_1 + push.12255682890262208133 +end + + +export.get_ark2_index_4_poly_coef_2 + push.15511186351910640359 +end + + +export.get_ark2_index_4_poly_coef_3 + push.4162444308275232160 +end + + +export.get_ark2_index_4_poly_coef_4 + push.18091011016833255590 +end + + +export.get_ark2_index_4_poly_coef_5 + push.9105441978990789270 +end + + +export.get_ark2_index_4_poly_coef_6 + push.13577569096164448709 +end + + +export.get_ark2_index_4_poly_coef_7 + push.13760205548494373198 +end + + +export.get_ark2_index_5_poly_coef_0 + push.13448103804003008392 +end + + +export.get_ark2_index_5_poly_coef_1 + push.10779183659020945945 +end + + +export.get_ark2_index_5_poly_coef_2 + push.13325354218459340225 +end + + +export.get_ark2_index_5_poly_coef_3 + push.14295910610635932367 +end + + +export.get_ark2_index_5_poly_coef_4 + push.8330371093400562539 +end + + +export.get_ark2_index_5_poly_coef_5 + push.12626397089873488158 +end + + +export.get_ark2_index_5_poly_coef_6 + push.14906872242999172719 +end + + +export.get_ark2_index_5_poly_coef_7 + push.16136339960217238365 +end + + +export.get_ark2_index_6_poly_coef_0 + push.1684770865143235919 +end + + +export.get_ark2_index_6_poly_coef_1 + push.5552056882756995901 +end + + +export.get_ark2_index_6_poly_coef_2 + push.4442419536195446696 +end + + +export.get_ark2_index_6_poly_coef_3 + push.232266114409147417 +end + + +export.get_ark2_index_6_poly_coef_4 + push.3314161303197956391 +end + + +export.get_ark2_index_6_poly_coef_5 + push.13532442853135532270 +end + + +export.get_ark2_index_6_poly_coef_6 + push.7914958773335845923 +end + + +export.get_ark2_index_6_poly_coef_7 + push.15091475497397269291 +end + + +export.get_ark2_index_7_poly_coef_0 + push.9634219295911269210 +end + + +export.get_ark2_index_7_poly_coef_1 + push.8265302361391121882 +end + + +export.get_ark2_index_7_poly_coef_2 + push.113009052876325830 +end + + +export.get_ark2_index_7_poly_coef_3 + push.5471962659021976827 +end + + +export.get_ark2_index_7_poly_coef_4 + push.16401896627521476325 +end + + +export.get_ark2_index_7_poly_coef_5 + push.15232515735988055298 +end + + +export.get_ark2_index_7_poly_coef_6 + push.18136037306670513314 +end + + +export.get_ark2_index_7_poly_coef_7 + push.10680270387070642097 +end + + +export.get_ark2_index_8_poly_coef_0 + push.4822559711433446189 +end + + +export.get_ark2_index_8_poly_coef_1 + push.2975769274803193496 +end + + +export.get_ark2_index_8_poly_coef_2 + push.11212733575482077029 +end + + +export.get_ark2_index_8_poly_coef_3 + push.3066360176188119622 +end + + +export.get_ark2_index_8_poly_coef_4 + push.6729123480959643901 +end + + +export.get_ark2_index_8_poly_coef_5 + push.927601220019329593 +end + + +export.get_ark2_index_8_poly_coef_6 + push.6019778753836356768 +end + + +export.get_ark2_index_8_poly_coef_7 + push.5596990898436677811 +end + + +export.get_ark2_index_9_poly_coef_0 + push.15684497769113983515 +end + + +export.get_ark2_index_9_poly_coef_1 + push.8545253256522768005 +end + + +export.get_ark2_index_9_poly_coef_2 + push.18215086275453877856 +end + + +export.get_ark2_index_9_poly_coef_3 + push.5016038390293382937 +end + + +export.get_ark2_index_9_poly_coef_4 + push.10346303444853625090 +end + + +export.get_ark2_index_9_poly_coef_5 + push.14397868846792134192 +end + + +export.get_ark2_index_9_poly_coef_6 + push.5834002991750433760 +end + + +export.get_ark2_index_9_poly_coef_7 + push.11338711761097304404 +end + + +export.get_ark2_index_10_poly_coef_0 + push.17520966244186076706 +end + + +export.get_ark2_index_10_poly_coef_1 + push.17628674693100098623 +end + + +export.get_ark2_index_10_poly_coef_2 + push.16883813969466615392 +end + + +export.get_ark2_index_10_poly_coef_3 + push.9443647939212324750 +end + + +export.get_ark2_index_10_poly_coef_4 + push.12928683089759827315 +end + + +export.get_ark2_index_10_poly_coef_5 + push.2645376024929508383 +end + + +export.get_ark2_index_10_poly_coef_6 + push.7237171422926818722 +end + + +export.get_ark2_index_10_poly_coef_7 + push.18008706076563744329 +end + + +export.get_ark2_index_11_poly_coef_0 + push.8182764617849825514 +end + + +export.get_ark2_index_11_poly_coef_1 + push.16332258635923638051 +end + + +export.get_ark2_index_11_poly_coef_2 + push.1569900429732542065 +end + + +export.get_ark2_index_11_poly_coef_3 + push.10042109738485744803 +end + + +export.get_ark2_index_11_poly_coef_4 + push.9638265557917565039 +end + + +export.get_ark2_index_11_poly_coef_5 + push.14826757489656136717 +end + + +export.get_ark2_index_11_poly_coef_6 + push.655724116770628941 +end + + +export.get_ark2_index_11_poly_coef_7 + push.8292530465339031919 +end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm index c64ff6d434..63b4f5f90a 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm @@ -91,12 +91,12 @@ export.init_seed.2 swapw # Lay out the proof context - push.3072 + push.0x0c00 # main segment width is 12 and there are 0 auxiliary segments movdn.4 - push.8 + push.0x08 # main segment length is 8 movdn.4 - push.1 - push.4294967295 + push.0x01 # lower half of the modulus + push.0xffffffff # upper half of the modulus # Hash the proof context, with the message as meta data # The reason for this hack is the need to have message as a public @@ -109,14 +109,12 @@ export.init_seed.2 hperm dropw dropw - #push.132127 - push.132103 - push.0 - push.8 + push.0x020407 # field extension degree || FRI folding factor || FRI remainder polynomial max degree + exec.constants::grinding_factor + exec.constants::blowup_factor # Number of FRI queries - push.100 - #push.122 + exec.constants::num_fri_queries movupw.2 @@ -443,27 +441,30 @@ export.generate_z_zN exec.constants::r1_ptr mem_loadw drop drop + # 2^0 dup.1 dup.1 + # 2^3 dup.1 dup.1 - repeat.2 + repeat.3 dup.1 dup.1 ext2mul end - # => [z4_1, z4_0, z_1, z_0, ...] + # => [z3_1, z3_0, z_1, z_0, z_1, z_0, ...] dup.1 dup.1 - repeat.2 + repeat.1 dup.1 dup.1 ext2mul end - # => [z16_1, z16_0, z4_1, z4_0, z_1, z_0, z_1, z_0, ...] - - dup.5 dup.5 - repeat.7 + # => [z4_1, z4_0, z3_1, z3_0, z_1, z_0, z_1, z_0, ...] + + dup.1 dup.1 + repeat.2 dup.1 dup.1 ext2mul end - # => [z16_1, z16_0, z16_1, z16_0, z4_1, z4_0, z_1, z_0, z_1, z_0, ...] + # => [z6_1, z6_0, z4_1, z4_0, z3_1, z3_0, z_1, z_0, z_1, z_0, ...] + repeat.3 ext2mul end @@ -609,9 +610,9 @@ end #! 485 + 31 * num_queries export.generate_list_indices # push the depth - push.11 + exec.constants::initial_lde_domain_log_size # push the mask - push.2047 + exec.constants::initial_lde_domain_size sub.1 #=> [mask, depth, query_ptr, num_queries] where depth = log(lde_size) # Get address holding the integers (this will later hold the FRI queries) diff --git a/stdlib/asm/crypto/dsa/rpo_stark/round_constants_polynomials.masm b/stdlib/asm/crypto/dsa/rpo_stark/round_constants_polynomials.masm new file mode 100644 index 0000000000..1110872fb4 --- /dev/null +++ b/stdlib/asm/crypto/dsa/rpo_stark/round_constants_polynomials.masm @@ -0,0 +1,1157 @@ +use.std::crypto::dsa::rpo_stark::permutation_constants + +# ROUND CONSTANT POLYNOMIALS EVALUATION PROCEDURES +# ================================================================================================= + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_0_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_0_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_0_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_0_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_0_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_0_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_0_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_0_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_0_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_0_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_1_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_1_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_1_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_1_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_1_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_1_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_1_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_1_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_1_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_1_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_2_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_2_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_2_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_2_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_2_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_2_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_2_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_2_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_2_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_2_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_3_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_3_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_3_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_3_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_3_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_3_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_3_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_3_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_3_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_3_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_4_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_4_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_4_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_4_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_4_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_4_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_4_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_4_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_4_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_4_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_5_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_5_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_5_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_5_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_5_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_5_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_5_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_5_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_5_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_5_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_6_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_6_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_6_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_6_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_6_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_6_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_6_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_6_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_6_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_6_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_7_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_7_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_7_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_7_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_7_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_7_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_7_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_7_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_7_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_7_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_8_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_8_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_8_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_8_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_8_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_8_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_8_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_8_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_8_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_8_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_9_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_9_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_9_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_9_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_9_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_9_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_9_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_9_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_9_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_9_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_10_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_10_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_10_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_10_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_10_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_10_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_10_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_10_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_10_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_10_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark1_index_11_at_z + + dup.1 + exec.permutation_constants::get_ark1_index_11_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark1_index_11_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark1_index_11_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_11_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_11_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_11_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_11_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_11_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark1_index_11_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_0_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_0_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_0_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_0_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_0_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_0_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_0_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_0_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_0_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_0_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_1_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_1_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_1_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_1_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_1_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_1_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_1_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_1_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_1_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_1_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_2_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_2_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_2_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_2_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_2_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_2_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_2_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_2_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_2_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_2_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_3_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_3_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_3_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_3_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_3_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_3_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_3_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_3_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_3_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_3_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_4_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_4_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_4_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_4_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_4_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_4_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_4_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_4_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_4_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_4_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_5_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_5_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_5_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_5_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_5_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_5_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_5_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_5_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_5_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_5_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_6_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_6_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_6_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_6_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_6_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_6_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_6_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_6_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_6_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_6_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_7_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_7_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_7_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_7_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_7_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_7_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_7_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_7_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_7_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_7_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_8_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_8_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_8_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_8_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_8_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_8_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_8_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_8_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_8_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_8_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_9_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_9_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_9_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_9_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_9_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_9_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_9_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_9_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_9_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_9_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_10_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_10_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_10_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_10_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_10_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_10_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_10_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_10_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_10_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_10_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + + +#! Input: [z1, z0, ...] +#! Output: [ev1, ev0, ...] +#! +#! Cycles: 68 +export.evaluate_ark2_index_11_at_z + + dup.1 + exec.permutation_constants::get_ark2_index_11_poly_coef_7 + mul + dup.1 + exec.permutation_constants::get_ark2_index_11_poly_coef_7 + mul + # => [acc1, acc0, z1, z0, ...] + swap exec.permutation_constants::get_ark2_index_11_poly_coef_6 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_11_poly_coef_5 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_11_poly_coef_4 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_11_poly_coef_3 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_11_poly_coef_2 add swap + # => [acc1, acc0, z1, z0, ...] + + dup.3 dup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_11_poly_coef_1 add swap + # => [acc1, acc0, z1, z0, ...] + + movup.3 movup.3 + ext2mul + swap exec.permutation_constants::get_ark2_index_11_poly_coef_0 add swap + # => [acc1, acc0, ...] +end + diff --git a/stdlib/asm/crypto/dsa/rpo_stark/utils.masm b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm index bc49309d58..112b76bf32 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/utils.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm @@ -6,70 +6,67 @@ use.std::crypto::fri::ext2fri #! #! Input: [...] #! Output: [...] -#! Cycles: 21 + 83 * num_fri_layers +#! Cycles: 270 export.load_fri_layer_commitments - # Load the first FRI layer commitment - padw adv_loadw - exec.constants::fri_com_ptr - mem_storew + # Add a counter and the number of iterations + push.0 + exec.constants::number_of_fri_layers push.2 mul + # => [number_of_iter, cnt, ...] - # Reseed - exec.random_coin::reseed_with_salt - # => [...] + # Compute the next log LDE size + exec.constants::initial_lde_domain_log_size + exec.constants::log_folding_factor + sub + # => [nxt_lde_log_size, number_of_iter, cnt, ...] - # Squeeze folding randomness alpha - exec.random_coin::get_rate_1 - drop drop - - # Append the LDE size and log size and store - push.9 - push.512 - exec.constants::fri_com_ptr add.1 - mem_storew + # Compute the next LDE size + exec.constants::initial_lde_domain_size + exec.constants::folding_factor + # Assumption: domain size is divisible by folding factor + div + # => [nxt_lde_size, nxt_lde_log_size, number_of_iter, cnt, ...] - # Load the second FRI layer commitment - adv_loadw - exec.constants::fri_com_ptr add.2 + dup.3 dup.3 + neq + while.true + padw adv_loadw + # => [Root, nxt_lde_size, nxt_lde_log_size, number_of_iter, cnt, ...] + dup.7 add.1 swap.8 + exec.constants::fri_com_ptr + add mem_storew # Reseed exec.random_coin::reseed_with_salt - # => [...] + # => [nxt_lde_size, nxt_lde_log_size, number_of_iter, cnt, ...] # Squeeze folding randomness alpha exec.random_coin::get_rate_1 drop drop + # => [a1, a0, nxt_lde_size, nxt_lde_log_size, number_of_iter, cnt, ...] # Append the LDE size and log size and store - push.7 - push.128 - exec.constants::fri_com_ptr add.3 - mem_storew + dup.3 exec.constants::log_folding_factor sub swap.4 + # => [nxt_lde_log_size, a1, a0, nxt_lde_size, nxt_lde_log_size - log_ff, number_of_iter, cnt, ...] + # => [nxt_lde_log_size, a1, a0, nxt_lde_size, nxt_lde_log_size - log_ff, number_of_iter, cnt, ...] + dup.3 exec.constants::folding_factor div swap.4 + # => [nxt_lde_size, nxt_lde_log_size, a1, a0, nxt_lde_size / ff, nxt_lde_log_size - log_ff, number_of_iter, cnt, ...] - # Load the third FRI layer commitment - adv_loadw - exec.constants::fri_com_ptr add.4 + dup.7 add.1 swap.8 + exec.constants::fri_com_ptr + add mem_storew + # => [nxt_lde_size, nxt_lde_log_size, a1, a0, nxt_lde_size / ff, nxt_lde_log_size - log_ff, number_of_iter, cnt, ...] - # Reseed - exec.random_coin::reseed_with_salt - # => [...] - - # Squeeze folding randomness alpha - exec.random_coin::get_rate_1 - drop drop - - # Append the LDE size and log size and store - push.5 - push.32 - exec.constants::fri_com_ptr add.5 - mem_storew - - # Clean up the stack dropw + # => [nxt_lde_size / ff, nxt_lde_log_size - log_ff, number_of_iter, cnt, ...] + + dup.3 dup.3 neq + end + dropw end #! Load the remainder polynomial from the advice provider and check that its hash corresponds @@ -80,38 +77,35 @@ end #! #! Input: [...] #! Output: [...] -#! Cycles: 1633 +#! Cycles: 1641 export.load_and_verify_remainder - # Load remainder commitment and save it at `TMP7` + # Load remainder commitment and save it at `TMP1` padw adv_loadw - exec.constants::tmp7 mem_storew + exec.constants::tmp1 mem_storew # Reseed with remainder commitment exec.random_coin::reseed_with_salt - # Capacity portion of the state - padw - - # Load the first 2 coefficients - padw - adv_loadw - - # The FRI layer commitments are stored at addresses ptr, ptr + 2, ptr + 4. The remainder will - # be stored in the region ptr + 6 to ptr + 6 + 16 - 1. Thus the remainder polynomial coefficients - # will be in the region ptr + 22 to ptr + 22 + 2 - 1 - exec.constants::fri_com_ptr add.22 mem_storew - - # Load the last 2 coefficients - padw - adv_loadw - exec.constants::fri_com_ptr add.23 mem_storew - - # Hash the remainder polynomial - hperm + # The FRI layer commitments are stored at addresses ptr, ..., ptr + REMAINDER_CODEWORD_OFFSET - 1. + # The remainder will be stored in the region ptr + REMAINDER_CODEWORD_OFFSET to + # ptr + REMAINDER_CODEWORD_OFFSET + SIZE_OF_REMAINDER_CODEWORD / 2 - 1. + # Thus the remainder polynomial coefficients will be in the region + # ptr + REMAINDER_CODEWORD_OFFSET + SIZE_OF_REMAINDER_CODEWORD / 2 to + # ptr + REMAINDER_CODEWORD_OFFSET + SIZE_OF_REMAINDER_CODEWORD / 2 + SIZE_OF_REMAINDER_POLY / 2 + exec.constants::fri_com_ptr + exec.constants::remainder_codeword_offset exec.constants::remainder_codeword_size_div_by_2 + add add + padw padw padw + # The remainder polynomial has degree less than 7 + repeat.2 + adv_pipe hperm + end + # Compare Remainder_poly_com with the read commitment - exec.constants::tmp7 mem_loadw + exec.constants::tmp1 mem_loadw + movup.4 assert_eq movup.3 @@ -124,7 +118,9 @@ export.load_and_verify_remainder # Load and hash the remainder codeword exec.constants::fri_com_ptr exec.constants::remainder_codeword_offset add movdn.4 padw padw - repeat.8 + + # The remainder codeword is of length 64 + repeat.16 adv_pipe hperm end # => [Y, R, Y] where R = [y, y, tau1, tau0] @@ -141,8 +137,8 @@ export.load_and_verify_remainder exec.constants::fri_com_ptr exec.constants::remainder_codeword_offset add movdn.2 # => [tau1, tau0, ptr_remainder, ... ] - exec.ext2fri::verify_remainder_32 - # Drop pointer - drop + exec.ext2fri::verify_remainder_64 + # Drop pointers + drop drop #=> [...] end \ No newline at end of file diff --git a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm index c622346c35..82cf88ab03 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm @@ -4,6 +4,7 @@ use.std::crypto::dsa::rpo_stark::deep_queries use.std::crypto::dsa::rpo_stark::fri use.std::crypto::dsa::rpo_stark::random_coin use.std::crypto::dsa::rpo_stark::utils +use.std::crypto::dsa::rpo_stark::constraints_evaluation # RPO-STARK-BASED SIGNATURE SCHEME VERIFICATION ALGORITHM @@ -18,7 +19,7 @@ use.std::crypto::dsa::rpo_stark::utils #! Input: [PK, MSG, ...] #! Output: [...] #! -#! Cycles: ~ xx +#! Cycles: ~ 13770 + 381 * num_queries + 81 * num_queries * num_layers export.verify #============================================================================================== @@ -81,11 +82,11 @@ export.verify # Cycles: 71 exec.random_coin::reseed_with_salt - + # Cycles: 160 exec.ood_frames::load_constraint_evaluations #=> [CONSTR_EVAL_HASH, ...] - + # Cycles: 71 exec.random_coin::reseed_with_salt #=> [...] @@ -94,6 +95,8 @@ export.verify # VI) Evaluate the constraints over the OOD frame and assert equality with H(z) #============================================================================================== + # Cycles: 8320 + exec.constraints_evaluation::deep_consistency_check #=> [...] #============================================================================================== @@ -128,7 +131,7 @@ export.verify # c) Check the NTT relationship. #============================================ - # Cycles: 1632 + # Cycles: 3090 exec.utils::load_and_verify_remainder #=> [...] @@ -167,7 +170,7 @@ export.verify # Cycles: 24 + num_queries * 315 exec.deep_queries::compute_deep_composition_polynomial_queries #=> [query_ptr, ...] - + #============================================ # 7) Call the FRI verifier #============================================ diff --git a/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs b/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs index 8899e9b091..1b65770bb5 100644 --- a/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs +++ b/stdlib/tests/crypto/fri/verifier_fri_e2f4.rs @@ -4,13 +4,11 @@ use processor::{ crypto::{Hasher, RandomCoin, RpoDigest, WinterRandomCoin}, Digest as MidenDigest, }; -use rand::SeedableRng; -use rand_chacha::ChaCha20Rng; use test_utils::{ crypto::{MerklePath, NodeIndex, PartialMerkleTree, Rpo256 as MidenHasher}, group_slice_elements, math::fft, - Felt, FieldElement, QuadFelt as QuadExt, StarkField, EMPTY_WORD, + Felt, FieldElement, MockPrng, QuadFelt as QuadExt, StarkField, EMPTY_WORD, }; use winter_crypto::VectorCommitment; use winter_fri::{ @@ -55,7 +53,9 @@ pub struct FriResult { // The main purpose of this function is to build the non-deterministic inputs needed to verify // a FRI proof inside the Miden VM. // The output is organized as follows: -pub fn fri_prove_verify_fold4_ext2>(trace_length_e: usize) -> Result { +pub fn fri_prove_verify_fold4_ext2>( + trace_length_e: usize, +) -> Result { let max_remainder_size_e = 3; let folding_factor_e = 2; let trace_length = 1 << trace_length_e; @@ -63,7 +63,6 @@ pub fn fri_prove_verify_fold4_ext2>(trace_leng let max_remainder_size = 1 << max_remainder_size_e; let folding_factor = 1 << folding_factor_e; let nonce = 0_u64; - let mut prng = ChaCha20Rng::from_entropy(); let options = FriOptions::new(lde_blowup, folding_factor, max_remainder_size); let mut channel = build_prover_channel(trace_length, &options); @@ -71,7 +70,7 @@ pub fn fri_prove_verify_fold4_ext2>(trace_leng // instantiate the prover and generate the proof let mut prover = FriProver::<_, _, _, VC>::new(options.clone()); - prover.build_layers(&mut channel, evaluations.clone(), &mut prng); + prover.build_layers(&mut channel, evaluations.clone()); let positions = channel.draw_query_positions(nonce); let proof = prover.build_proof(&positions); @@ -126,8 +125,8 @@ pub fn fri_prove_verify_fold4_ext2>(trace_leng pub fn build_prover_channel( trace_length: usize, options: &FriOptions, -) -> DefaultProverChannel> { - DefaultProverChannel::new(trace_length * options.blowup_factor(), 32, false) +) -> DefaultProverChannel> { + DefaultProverChannel::new(trace_length * options.blowup_factor(), 32, false, None) } pub fn build_evaluations(trace_length: usize, lde_blowup: usize) -> Vec { diff --git a/stdlib/tests/crypto/stark/mod.rs b/stdlib/tests/crypto/stark/mod.rs index 752e829829..7b2527822b 100644 --- a/stdlib/tests/crypto/stark/mod.rs +++ b/stdlib/tests/crypto/stark/mod.rs @@ -80,7 +80,6 @@ fn generate_signature_data() -> Result { let message = rand_array(); let signature = sk.sign(message); let proof = signature.inner(); - let pub_inputs = SignaturePublicInputs::new(pk.inner(), message); let res = generate_advice_inputs_signature(proof, pub_inputs); diff --git a/stdlib/tests/crypto/stark/signature/channel.rs b/stdlib/tests/crypto/stark/signature/channel.rs new file mode 100644 index 0000000000..894f2316ec --- /dev/null +++ b/stdlib/tests/crypto/stark/signature/channel.rs @@ -0,0 +1,442 @@ +use alloc::vec::Vec; + +use assembly::utils::Deserializable; +use rand_chacha::ChaCha20Rng; +use test_utils::{ + crypto::{rpo_stark::RescueAir, BatchMerkleProof, PartialMerkleTree, Rpo256, RpoDigest}, + group_slice_elements, + math::{FieldElement, QuadExtension, StarkField}, + Felt, VerifierError, +}; +use winter_air::{ + proof::{Proof, Queries, Table, TraceOodFrame}, + Air, +}; +use winter_crypto::{SaltedMerkleTree, VectorCommitment}; +use winter_fri::{folding::fold_positions, VerifierChannel as FriVerifierChannel}; + +pub type QuadExt = QuadExtension; + +type AdvMap = Vec<(RpoDigest, Vec)>; +type SaltedBatchMerkleProof = (Vec, BatchMerkleProof); +/// A view into a [Proof] for a computation structured to simulate an "interactive" channel. +/// +/// A channel is instantiated for a specific proof, which is parsed into structs over the +/// appropriate field (specified by type parameter `E`). This also validates that the proof is +/// well-formed in the context of the computation for the specified [Air]. +pub struct VerifierChannel { + // trace queries + trace_roots: Vec, + trace_queries: Option, + // constraint queries + constraint_root: RpoDigest, + constraint_queries: Option, + // FRI proof + fri_roots: Option>, + fri_layer_proofs: Vec>, + fri_layer_queries: Vec>, + fri_remainder: Option>, + fri_num_partitions: usize, + fri_salts: Vec>, + // out-of-domain frame + ood_trace_frame: Option>, + ood_constraint_evaluations: Option>, + // query proof-of-work + pow_nonce: u64, + salts: Vec>, +} + +impl VerifierChannel { + // CONSTRUCTOR + // -------------------------------------------------------------------------------------------- + /// Creates and returns a new [VerifierChannel] initialized from the specified `proof`. + pub fn new(air: &RescueAir, proof: Proof) -> Result { + let Proof { + context, + commitments, + trace_queries, + constraint_queries, + ood_frame, + fri_proof, + pow_nonce, + num_unique_queries, + gkr_proof: _, + salts, + } = proof; + + // make AIR and proof base fields are the same + if Felt::get_modulus_le_bytes() != context.field_modulus_bytes() { + return Err(VerifierError::InconsistentBaseField); + } + + let num_trace_segments = air.trace_info().num_segments(); + let main_trace_width = air.trace_info().main_trace_width(); + let aux_trace_width = air.trace_info().aux_segment_width(); + let lde_domain_size = air.lde_domain_size(); + let fri_options = air.options().to_fri_options(); + let constraint_frame_width = air.context().num_constraint_composition_columns(); + + // --- parse commitments ------------------------------------------------------------------ + let (trace_roots, constraint_root, fri_roots) = commitments + .parse::(num_trace_segments, fri_options.num_fri_layers(lde_domain_size)) + .map_err(|err| VerifierError::ProofDeserializationError(err.to_string()))?; + // --- parse trace and constraint queries ------------------------------------------------- + let trace_queries = TraceQueries::new(trace_queries, air, num_unique_queries as usize)?; + let constraint_queries = + ConstraintQueries::new(constraint_queries, air, num_unique_queries as usize)?; + + // --- parse FRI proofs ------------------------------------------------------------------- + let fri_num_partitions = fri_proof.num_partitions(); + let fri_remainder = fri_proof + .parse_remainder() + .map_err(|err| VerifierError::ProofDeserializationError(err.to_string()))?; + + let fri_salts = fri_proof + .parse_salts::() + .map_err(|err| VerifierError::ProofDeserializationError(err.to_string()))?; + let (fri_layer_queries, fri_layer_proofs) = fri_proof + .parse_layers::>( + lde_domain_size, + fri_options.folding_factor(), + ) + .map_err(|err| VerifierError::ProofDeserializationError(err.to_string()))?; + + // --- parse out-of-domain evaluation frame ----------------------------------------------- + let (ood_trace_evaluations, ood_constraint_evaluations) = ood_frame + .parse(main_trace_width, aux_trace_width, constraint_frame_width) + .map_err(|err| VerifierError::ProofDeserializationError(err.to_string()))?; + + // --- parse Fiat-Shamir salts ----------------------------------------------- + let salts: Vec> = Vec::read_from_bytes(&salts) + .map_err(|err| VerifierError::ProofDeserializationError(err.to_string()))?; + + Ok(VerifierChannel { + // trace queries + trace_roots, + trace_queries: Some(trace_queries), + // constraint queries + constraint_root, + constraint_queries: Some(constraint_queries), + // FRI proof + fri_roots: Some(fri_roots), + fri_layer_proofs, + fri_layer_queries, + fri_remainder: Some(fri_remainder), + fri_num_partitions, + fri_salts, + // out-of-domain evaluation + ood_trace_frame: Some(ood_trace_evaluations), + ood_constraint_evaluations: Some(ood_constraint_evaluations), + // query seed + pow_nonce, + // FS salts + salts, + }) + } + + // DATA READERS + // -------------------------------------------------------------------------------------------- + + /// Returns execution trace commitments sent by the prover. + /// + /// For computations requiring multiple trace segment, the returned slice will contain a + /// commitment for each trace segment. + pub fn read_trace_commitments(&self) -> &[RpoDigest] { + &self.trace_roots + } + + /// Returns constraint evaluation commitment sent by the prover. + pub fn read_constraint_commitment(&self) -> RpoDigest { + self.constraint_root + } + + /// Returns trace polynomial evaluations at out-of-domain points z and z * g, where g is the + /// generator of the LDE domain. + /// + /// For computations requiring multiple trace segments, evaluations of auxiliary trace + /// polynomials are also included as the second value of the returned tuple. Otherwise, the + /// second value is None. + pub fn read_ood_trace_frame(&mut self) -> TraceOodFrame { + self.ood_trace_frame.take().expect("already read") + } + + /// Returns evaluations of composition polynomial columns at z^m, where z is the out-of-domain + /// point, and m is the number of composition polynomial columns. + pub fn read_ood_constraint_evaluations(&mut self) -> Vec { + let res = self.ood_constraint_evaluations.take().expect("already read"); + res + } + + /// Returns query proof-of-work nonce sent by the prover. + pub fn read_pow_nonce(&self) -> u64 { + self.pow_nonce + } + + /// Returns the salts needed for Fiat-Shamir. + pub fn read_salts(&self) -> Vec> { + self.salts.clone() + } + + /// Returns the salts needed for Fiat-Shamir in FRI. + pub(crate) fn read_fri_salts(&self) -> Vec> { + self.fri_salts.clone() + } + + /// Returns trace states at the specified positions of the LDE domain. This also checks if + /// the trace states are valid against the trace commitment sent by the prover. + #[allow(clippy::type_complexity)] + pub fn read_queried_trace_states( + &mut self, + positions: &[usize], + ) -> Result<(AdvMap, Vec), VerifierError> { + let queries = self.trace_queries.take().expect("already read"); + let proofs = queries.query_proofs; + let main_queries = queries.main_states; + let main_queries_vec: Vec> = main_queries.rows().map(|a| a.to_owned()).collect(); + + let (main_trace_pmt, main_trace_adv_map) = + unbatch_to_partial_mt(positions.to_vec(), main_queries_vec, proofs[0].clone()); + + let trees = vec![main_trace_pmt]; + + Ok((main_trace_adv_map, trees)) + } + + /// Returns constraint evaluations at the specified positions of the LDE domain. This also + /// checks if the constraint evaluations are valid against the constraint commitment sent by + /// the prover. + pub fn read_constraint_evaluations( + &mut self, + positions: &[usize], + ) -> Result<(AdvMap, PartialMerkleTree), VerifierError> { + let queries = self.constraint_queries.take().expect("already read"); + let proof = queries.query_proofs; + + let queries = queries + .evaluations + .rows() + .map(|a| QuadExt::slice_as_base_elements(a).into()) + .collect(); + let (constraint_pmt, constraint_adv_map) = + unbatch_to_partial_mt(positions.to_vec(), queries, proof); + + Ok((constraint_adv_map, constraint_pmt)) + } + + /// Returns the FRI layers Merkle batch proofs. + pub fn fri_layer_proofs(&self) -> Vec> { + self.fri_layer_proofs.clone() + } + + /// Returns the unbatched Merkle proofs as well as a global key-value map for all the FRI layer + /// proofs. + pub fn unbatch_fri_layer_proofs( + &mut self, + positions_: &[usize], + domain_size: usize, + layer_commitments: Vec, + ) -> (Vec, Vec<(RpoDigest, Vec)>) { + let all_layers_queries = self.fri_layer_queries.clone(); + let mut current_domain_size = domain_size; + let mut positions = positions_.to_vec(); + let number_of_folds = layer_commitments.len() - 1; + + let mut global_adv_key_map = Vec::new(); + let mut global_partial_merkle_trees = Vec::new(); + let mut layer_proofs = self.fri_layer_proofs(); + for current_layer_queries in all_layers_queries.iter().take(number_of_folds) { + let mut folded_positions = fold_positions(&positions, current_domain_size, N); + + let layer_proof = layer_proofs.remove(0); + let queries: Vec<_> = group_slice_elements::(current_layer_queries) + .iter() + .map(|query| QuadExt::slice_as_base_elements(query).to_vec()) + .collect(); + + let (current_partial_merkle_tree, mut cur_adv_key_map) = + unbatch_to_partial_mt(folded_positions.clone(), queries, layer_proof); + + global_partial_merkle_trees.push(current_partial_merkle_tree); + global_adv_key_map.append(&mut cur_adv_key_map); + + core::mem::swap(&mut positions, &mut folded_positions); + current_domain_size /= N; + } + + (global_partial_merkle_trees, global_adv_key_map) + } +} + +// FRI VERIFIER CHANNEL IMPLEMENTATION +// ================================================================================================ + +impl FriVerifierChannel for VerifierChannel { + type Hasher = Rpo256; + type VectorCommitment = SaltedMerkleTree; + + fn read_fri_num_partitions(&self) -> usize { + self.fri_num_partitions + } + + fn read_fri_layer_commitments(&mut self) -> Vec { + self.fri_roots.take().expect("already read") + } + + fn take_next_fri_layer_proof( + &mut self, + ) -> >::MultiProof { + self.fri_layer_proofs.remove(0) + } + + fn take_next_fri_layer_queries(&mut self) -> Vec { + self.fri_layer_queries.remove(0) + } + + fn take_fri_remainder(&mut self) -> Vec { + self.fri_remainder.take().expect("already read") + } + + fn take_salt(&mut self) -> Option<::Digest> { + self.salts.remove(0) + } +} + +// TRACE QUERIES +// ================================================================================================ + +/// Container of trace query data, including: +/// * Queried states for main trace segment. +/// * Merkle authentication paths for all queries. +struct TraceQueries { + query_proofs: Vec>, + main_states: Table, +} + +impl TraceQueries { + /// Parses the provided trace queries into trace states in the specified field and + /// corresponding Merkle authentication paths. + pub fn new( + mut queries: Vec, + air: &RescueAir, + num_queries: usize, + ) -> Result { + // parse main trace segment queries; parsing also validates that hashes of each table row + // form the leaves of Merkle authentication paths in the proofs + let main_segment_width = air.trace_info().main_trace_width(); + let main_segment_queries = queries.remove(0); + let (main_segment_query_proofs, main_segment_states) = main_segment_queries + .parse::>( + air.lde_domain_size(), + num_queries, + main_segment_width, + ) + .map_err(|err| { + VerifierError::ProofDeserializationError(format!( + "main trace segment query deserialization failed: {err}" + )) + })?; + + // all query proofs will be aggregated into a single vector + let query_proofs = vec![main_segment_query_proofs]; + + Ok(Self { + query_proofs, + main_states: main_segment_states, + }) + } +} + +// CONSTRAINT QUERIES +// ================================================================================================ + +/// Container of constraint evaluation query data, including: +/// * Queried constraint evaluation values. +/// * Merkle authentication paths for all queries. +struct ConstraintQueries { + query_proofs: SaltedBatchMerkleProof, + evaluations: Table, +} + +impl ConstraintQueries { + /// Parses the provided constraint queries into evaluations in the specified field and + /// corresponding Merkle authentication paths. + pub fn new( + queries: Queries, + air: &RescueAir, + num_queries: usize, + ) -> Result { + let constraint_frame_width = air.context().num_constraint_composition_columns() + 1; + + let (query_proofs, evaluations) = queries + .parse::>( + air.lde_domain_size(), + num_queries, + constraint_frame_width, + ) + .map_err(|err| { + VerifierError::ProofDeserializationError(format!( + "constraint evaluation query deserialization failed: {err}" + )) + })?; + + Ok(Self { query_proofs, evaluations }) + } +} + +// HELPER FUNCTIONS +// ================================================================================================ + +/// Takes a set of positions, query values of a trace at these positions and a Merkle batch proof +/// against a committment to this trace, and outputs a partial Merkle tree with individual Merkle +/// paths for each position as well as a key-value map mapping the digests of the query values +/// (i.e. Merkle tree leaves) to their corresponding query values. +pub fn unbatch_to_partial_mt( + positions: Vec, + queries: Vec>, + proof: SaltedBatchMerkleProof, +) -> (PartialMerkleTree, Vec<(RpoDigest, Vec)>) { + // hash the query values with the salts in order to get the leaf + let (salts, proof) = proof; + let leaves: Vec = queries + .iter() + .zip(salts.iter()) + .map(|(row, salt)| { + let leaf = Rpo256::hash_elements(row); + Rpo256::merge(&[leaf, *salt]) + }) + .collect(); + // use the computed leaves with the indices in order to unbatch the Merkle proof batch proof + let unbatched_proof = proof + .into_openings(&leaves, &positions) + .expect("failed to unbatch the batched Merkle proof"); + + // construct the partial Merkle tree data + let mut paths_with_leaves = vec![]; + for (position, merkle_proof) in positions.iter().zip(unbatched_proof.iter()) { + paths_with_leaves.push(( + *position as u64, + merkle_proof.0.to_owned(), + merkle_proof.1.to_owned().into(), + )) + } + + // construct the advice key map linking leaves to query values + let mut adv_key_map = Vec::new(); + leaves.into_iter().zip(queries.iter().zip(salts.iter())).for_each( + |(leaf, (query_data, salt))| { + adv_key_map.push(( + leaf, + query_data + .to_owned() + .into_iter() + .chain(salt.as_elements().to_owned().into_iter()) + .collect(), + )); + }, + ); + + ( + PartialMerkleTree::with_paths(paths_with_leaves).expect("should not fail from paths"), + adv_key_map, + ) +} diff --git a/stdlib/tests/crypto/stark/signature/mod.rs b/stdlib/tests/crypto/stark/signature/mod.rs new file mode 100644 index 0000000000..7c37efce56 --- /dev/null +++ b/stdlib/tests/crypto/stark/signature/mod.rs @@ -0,0 +1,189 @@ +use alloc::vec::Vec; + +use processor::crypto::RpoRandomCoin; +use test_utils::{ + crypto::{rpo_stark::RescueAir, MerkleStore, RandomCoin, Rpo256, RpoDigest}, + math::{fft, FieldElement, QuadExtension, StarkField, ToElements}, + Felt, VerifierError, +}; +use winter_air::{proof::Proof, Air}; +use winter_fri::VerifierChannel as FriVerifierChannel; + +mod channel; +use channel::VerifierChannel; + +pub const BLOWUP_FACTOR: usize = 8; +pub type QuadExt = QuadExtension; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct VerifierData { + pub initial_stack: Vec, + pub tape: Vec, + pub store: MerkleStore, + pub advice_map: Vec<(RpoDigest, Vec)>, +} + +pub fn generate_advice_inputs_signature( + proof: Proof, + pub_inputs: ::PublicInputs, +) -> Result { + // we need to provide the following instance specific data through the operand stack + let initial_stack = pub_inputs.to_elements().iter().map(|a| a.as_int()).collect(); + + // build a seed for the public coin; the initial seed is the hash of public inputs and proof + // context, but as the protocol progresses, the coin will be reseeded with the info received + // from the prover + let mut tape = vec![]; + let mut public_coin_seed = proof.context.to_elements(); + + public_coin_seed.append(&mut pub_inputs.to_elements()); + + // create AIR instance for the computation specified in the proof + let air = RescueAir::new(proof.trace_info().to_owned(), pub_inputs, proof.options().clone()); + let seed_digest = Rpo256::hash_elements(&public_coin_seed); + let mut public_coin: RpoRandomCoin = RpoRandomCoin::new(seed_digest.into()); + let mut channel = VerifierChannel::new(&air, proof)?; + let mut fs_salts = channel.read_salts(); + + // 1 ----- main segment trace ----------------------------------------------------------------- + let trace_commitments = channel.read_trace_commitments(); + + // reseed the coin with the commitment to the main segment trace + let fs_salt = fs_salts.remove(0); + public_coin.reseed_with_salt(trace_commitments[0], fs_salt); + tape.extend_from_slice(&digest_to_int_vec(trace_commitments)); + tape.extend_from_slice(&digest_to_int_vec(&[fs_salt.unwrap()])); + + // 2 ----- constraint composition trace ------------------------------------------------------- + + // build random coefficients for the composition polynomial. we don't need them but we have to + // generate them in order to update the random coin + let _constraint_coeffs: winter_air::ConstraintCompositionCoefficients = air + .get_constraint_composition_coefficients(&mut public_coin) + .map_err(|_| VerifierError::RandomCoinError)?; + let constraint_commitment = channel.read_constraint_commitment(); + let fs_salt = fs_salts.remove(0); + public_coin.reseed_with_salt(constraint_commitment, fs_salt); + tape.extend_from_slice(&digest_to_int_vec(&[constraint_commitment])); + tape.extend_from_slice(&digest_to_int_vec(&[fs_salt.unwrap()])); + + // 3 ----- OOD frames -------------------------------------------------------------- + + // generate the the OOD point + let _z: QuadExt = public_coin.draw().unwrap(); + + // read the main and auxiliary segments' OOD frames and add them to advice tape + let ood_trace_frame = channel.read_ood_trace_frame(); + let _ood_main_trace_frame = ood_trace_frame.main_frame(); + let _ood_aux_trace_frame = ood_trace_frame.aux_frame(); + + let mut main_frame_states = Vec::new(); + for col in 0.._ood_main_trace_frame.current().len() { + main_frame_states.push(_ood_main_trace_frame.current()[col]); + main_frame_states.push(_ood_main_trace_frame.next()[col]); + } + + let fs_salt = fs_salts.remove(0); + public_coin.reseed_with_salt(Rpo256::hash_elements(&main_frame_states), fs_salt); + tape.extend_from_slice(&to_int_vec(&main_frame_states)); + tape.extend_from_slice(&digest_to_int_vec(&[fs_salt.unwrap()])); + + // read OOD evaluations of composition polynomial columns + let ood_constraint_evaluations = channel.read_ood_constraint_evaluations(); + let fs_salt = fs_salts.remove(0); + public_coin.reseed_with_salt(Rpo256::hash_elements(&ood_constraint_evaluations), fs_salt); + tape.extend_from_slice(&to_int_vec(&ood_constraint_evaluations)); + tape.extend_from_slice(&digest_to_int_vec(&[fs_salt.unwrap()])); + assert!(fs_salts.is_empty()); + + // 4 ----- FRI ------------------------------------------------------------------------------- + + // read the FRI layer committments as well as remainder polynomial + let fri_commitments_digests = channel.read_fri_layer_commitments(); + let mut salts = channel.read_fri_salts(); + let poly = channel.read_remainder().unwrap(); + + // Reed-Solomon encode the remainder polynomial as this is needed for the probabilistic NTT + let twiddles = fft::get_twiddles(poly.len()); + let fri_remainder = + fft::evaluate_poly_with_offset(&poly, &twiddles, Felt::GENERATOR, BLOWUP_FACTOR); + + let fri_commitments_and_salts: Vec = fri_commitments_digests + .iter() + .zip(salts.iter()) + .flat_map(|(com, salt)| [*com, salt.unwrap()]) + .collect(); + // add the above to the advice tape + let fri_commitments: Vec = digest_to_int_vec(&fri_commitments_and_salts); + tape.extend_from_slice(&fri_commitments); + tape.extend_from_slice(&to_int_vec(&poly)); + tape.extend_from_slice(&to_int_vec(&fri_remainder)); + + // reseed with FRI layer commitments + let _deep_coefficients = air + .get_deep_composition_coefficients::(&mut public_coin) + .map_err(|_| VerifierError::RandomCoinError)?; + let layer_commitments = fri_commitments_digests.clone(); + for commitment in layer_commitments.iter() { + let salt = salts.remove(0); + public_coin.reseed_with_salt(*commitment, salt); + let _alpha: QuadExt = public_coin.draw().expect("failed to draw random indices"); + } + + // 5 ----- trace and constraint queries ------------------------------------------------------- + + // read proof-of-work nonce sent by the prover and draw pseudo-random query positions for + // the LDE domain from the public coin + let pow_nonce = channel.read_pow_nonce(); + let mut query_positions = public_coin + .draw_integers(air.options().num_queries(), air.lde_domain_size(), pow_nonce) + .map_err(|_| VerifierError::RandomCoinError)?; + tape.extend_from_slice(&[pow_nonce]); + query_positions.sort(); + query_positions.dedup(); + + // read advice maps and Merkle paths of the queries to main/aux and constraint composition + // traces + let (mut main_aux_adv_map, mut partial_trees_traces) = + channel.read_queried_trace_states(&query_positions)?; + let (mut constraint_adv_map, partial_tree_constraint) = + channel.read_constraint_evaluations(&query_positions)?; + let (mut partial_trees_fri, mut fri_adv_map) = channel.unbatch_fri_layer_proofs::<4>( + &query_positions, + air.lde_domain_size(), + fri_commitments_digests, + ); + + // consolidate advice maps + main_aux_adv_map.append(&mut constraint_adv_map); + main_aux_adv_map.append(&mut fri_adv_map); + + // build the full MerkleStore + partial_trees_fri.append(&mut partial_trees_traces); + partial_trees_fri.push(partial_tree_constraint); + let mut store = MerkleStore::new(); + for partial_tree in &partial_trees_fri { + store.extend(partial_tree.inner_nodes()); + } + + Ok(VerifierData { + initial_stack, + tape, + store, + advice_map: main_aux_adv_map, + }) +} + +// HELPER FUNCTIONS +// ================================================================================================ + +pub fn digest_to_int_vec(digest: &[RpoDigest]) -> Vec { + digest + .iter() + .flat_map(|digest| digest.as_elements().iter().map(|e| e.as_int())) + .collect() +} + +pub fn to_int_vec(ext_felts: &[QuadExt]) -> Vec { + QuadExt::slice_as_base_elements(ext_felts).iter().map(|e| e.as_int()).collect() +} diff --git a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs index 902ae9abe2..f0afb7003c 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/channel.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/channel.rs @@ -283,7 +283,7 @@ impl FriVerifierChannel for VerifierChannel { fn take_fri_remainder(&mut self) -> Vec { self.fri_remainder.take().expect("already read") } - + fn take_salt(&mut self) -> Option<::Digest> { todo!() } diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index 2d048db53f..95b8198248 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -23,7 +23,7 @@ pub use processor::{ }; #[cfg(not(target_family = "wasm"))] use proptest::prelude::{Arbitrary, Strategy}; -pub use prover::{prove, MemAdviceProvider, MerkleTreeVC, ProvingOptions}; +pub use prover::{prove, MemAdviceProvider, MerkleTreeVC, MockPrng, ProvingOptions}; pub use test_case::test_case; pub use verifier::{verify, AcceptableOptions, VerifierError}; use vm_core::{chiplets::hasher::apply_permutation, ProgramInfo}; From 24a52ce43c85fbe3f2ec19cb785897a8ffb8d095 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:31:20 +0100 Subject: [PATCH 13/19] fix: clippy --- stdlib/tests/crypto/stark/signature/channel.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/stdlib/tests/crypto/stark/signature/channel.rs b/stdlib/tests/crypto/stark/signature/channel.rs index 894f2316ec..fb73bd3d08 100644 --- a/stdlib/tests/crypto/stark/signature/channel.rs +++ b/stdlib/tests/crypto/stark/signature/channel.rs @@ -163,8 +163,7 @@ impl VerifierChannel { /// Returns evaluations of composition polynomial columns at z^m, where z is the out-of-domain /// point, and m is the number of composition polynomial columns. pub fn read_ood_constraint_evaluations(&mut self) -> Vec { - let res = self.ood_constraint_evaluations.take().expect("already read"); - res + self.ood_constraint_evaluations.take().expect("already read") } /// Returns query proof-of-work nonce sent by the prover. @@ -426,11 +425,7 @@ pub fn unbatch_to_partial_mt( |(leaf, (query_data, salt))| { adv_key_map.push(( leaf, - query_data - .to_owned() - .into_iter() - .chain(salt.as_elements().to_owned().into_iter()) - .collect(), + query_data.iter().copied().chain(salt.as_elements().iter().copied()).collect(), )); }, ); From 55d014d7fbb5b6460f71c33b2385e25c3d4a6d1f Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:05:31 +0100 Subject: [PATCH 14/19] chore: rebase on next and fix --- Cargo.lock | 136 ++++++++++++++++++++-------------------------- Cargo.toml | 18 +++--- prover/Cargo.toml | 2 +- prover/src/lib.rs | 9 ++- 4 files changed, 78 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bfad78bbae..9c79fed586 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,9 +186,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake3" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" dependencies = [ "arrayref", "arrayvec", @@ -243,9 +243,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "jobserver", "libc", @@ -546,12 +546,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -775,9 +775,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -826,9 +826,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -841,10 +841,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -892,9 +893,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libm" @@ -1053,7 +1054,7 @@ dependencies = [ [[package]] name = "miden-crypto" version = "0.12.0" -source = "git+https://github.com/0xPolygonMiden/crypto?branch=al-stark-signature-dev-masm#eaa1db66fbef27a2fea35586a425dc29fe421108" +source = "git+https://github.com/0xPolygonMiden/crypto?branch=al-stark-signature-dev-masm#866fda603af0ccdd8534df7d297ca9099bcc660c" dependencies = [ "blake3", "cc", @@ -2008,18 +2009,18 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "supports-color" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8775305acf21c96926c900ad056abeef436701108518cf890020387236ac5a77" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" dependencies = [ "is_ci", ] [[package]] name = "supports-hyperlinks" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee" +checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" [[package]] name = "supports-unicode" @@ -2029,9 +2030,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -2222,9 +2223,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -2233,9 +2234,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -2244,9 +2245,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -2278,9 +2279,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -2429,9 +2430,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", "once_cell", @@ -2440,9 +2441,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", @@ -2455,9 +2456,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2465,9 +2466,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", @@ -2478,15 +2479,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" dependencies = [ "js-sys", "wasm-bindgen", @@ -2746,8 +2747,8 @@ dependencies = [ [[package]] name = "winter-air" -version = "0.10.0" -source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#c6542eb717e73baaeda156dafe0ab187089a995f" +version = "0.11.0" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "libm", "winter-crypto 0.11.0", @@ -2758,26 +2759,13 @@ dependencies = [ [[package]] name = "winter-crypto" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcae1ada055aa10554910ecffc106cb116a19dba11ac91390ef982f94adb9c5" +version = "0.11.0" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "blake3", "rand", "rand_chacha", "sha3", - "winter-math 0.10.2", - "winter-utils 0.10.2", -] - -[[package]] -name = "winter-crypto" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c57748fd2da77742be601f03eda639ff6046879738fd1faae86e80018263cb" -dependencies = [ - "blake3", - "sha3", "winter-math 0.11.0", "winter-utils 0.11.0", ] @@ -2785,10 +2773,11 @@ dependencies = [ [[package]] name = "winter-fri" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9f999bc248c6254138b627035cb6d2c319580eb37dadcab6672298dbf00e41" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ - "winter-crypto 0.11.0", + "rand", + "rand_chacha", + "winter-crypto", "winter-math 0.11.0", "winter-utils 0.11.0", ] @@ -2805,8 +2794,7 @@ dependencies = [ [[package]] name = "winter-math" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6020c17839fa107ce4a7cc178e407ebbc24adfac1980f4fa2111198e052700ab" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "winter-utils 0.11.0", ] @@ -2814,8 +2802,7 @@ dependencies = [ [[package]] name = "winter-maybe-async" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ce144fde121b98523bb8a6c15a311773e1d534d33c1cb47f5580bba9cff8e7" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "quote", "syn", @@ -2824,8 +2811,7 @@ dependencies = [ [[package]] name = "winter-prover" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c2f3cf80955f084fd614c86883195331116b6c96dc88532d43d6836bd7adee" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "rand", "rand_chacha", @@ -2835,14 +2821,14 @@ dependencies = [ "winter-fri", "winter-math 0.11.0", "winter-maybe-async", + "winter-rand-utils", "winter-utils 0.11.0", ] [[package]] name = "winter-rand-utils" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226e4c455f6eb72f64ac6eeb7642df25e21ff2280a4f6b09db75392ad6b390ef" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "rand", "winter-utils 0.11.0", @@ -2857,8 +2843,7 @@ checksum = "1f948e71ffd482aa13d0ec3349047f81ecdb89f3b3287577973dcbf092a25fb4" [[package]] name = "winter-utils" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1507ef312ea5569d54c2c7446a18b82143eb2a2e21f5c3ec7cfbe8200c03bd7c" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "rayon", ] @@ -2866,8 +2851,7 @@ dependencies = [ [[package]] name = "winter-verifier" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d949eab6c26328733477ec56ca054fdc69c0c1b8267fa03d8b618ffe2193c4" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "winter-air", "winter-crypto 0.11.0", @@ -2878,8 +2862,8 @@ dependencies = [ [[package]] name = "winterfell" -version = "0.10.0" -source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#c6542eb717e73baaeda156dafe0ab187089a995f" +version = "0.11.0" +source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "winter-air", "winter-prover", diff --git a/Cargo.toml b/Cargo.toml index 0c3db8a4bc..f8039071f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,14 +35,14 @@ overflow-checks = true [patch.crates-io] -winter-air = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-crypto = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-prover = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-verifier = { git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-math = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-fri = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-maybe-async = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-utils = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } -winter-rand-utils = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk' } +winter-air = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-air' } +winter-crypto = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-crypto' } +winter-prover = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-prover' } +winter-verifier = { git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-verifier' } +winter-math = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-math' } +winter-fri = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-fri' } +winter-maybe-async = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-maybe-async' } +winter-utils = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-utils' } +winter-rand-utils = {git = 'https://github.com/Al-Kindi-0/winterfell', branch = 'al-zk', package = 'winter-rand-utils' } miden-crypto = {git = 'https://github.com/0xPolygonMiden/crypto', branch = 'al-stark-signature-dev-masm' } diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 7440b482a8..3143c3dd6d 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -27,7 +27,7 @@ tracing = { version = "0.1", default-features = false, features = ["attributes"] winter-maybe-async = { package = "winter-maybe-async", version = "0.11", default-features = false } winter-prover = { package = "winter-prover", version = "0.11", default-features = false } -winter-air = { version = "0.10", default-features = false } +winter-air = { version = "0.11", default-features = false } rand_chacha = { version = "0.3", default-features = false } [target.'cfg(all(target_arch = "aarch64", target_os = "macos"))'.dependencies] diff --git a/prover/src/lib.rs b/prover/src/lib.rs index dd8026d214..dc39868e8b 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -189,6 +189,8 @@ where type VC = MerkleTreeVC; type RandomCoin = R; type TraceLde> = DefaultTraceLde; + type ConstraintCommitment> = + DefaultConstraintCommitment; type ConstraintEvaluator<'a, E: FieldElement> = DefaultConstraintEvaluator<'a, ProcessorAir, E>; type ConstraintCommitment> = @@ -247,19 +249,24 @@ where trace.build_aux_trace(aux_rand_elements.rand_elements()).unwrap() } + #[instrument(skip_all)] #[maybe_async] - fn build_constraint_commitment>( + fn build_constraint_commitment>( &self, composition_poly_trace: CompositionPolyTrace, num_constraint_composition_columns: usize, domain: &StarkDomain, partition_options: PartitionOptions, + zk_parameters: Option, + prng: &mut Option, ) -> (Self::ConstraintCommitment, CompositionPoly) { DefaultConstraintCommitment::new( composition_poly_trace, num_constraint_composition_columns, domain, partition_options, + zk_parameters, + prng, ) } } From 638ba94c2e15b595d57f1b03199031ccf07cfdb7 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:20:51 +0100 Subject: [PATCH 15/19] chore: rebase --- stdlib/Cargo.toml | 2 +- stdlib/tests/crypto/stark/mod.rs | 8 ++++++-- stdlib/tests/crypto/stark/signature/mod.rs | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/stdlib/Cargo.toml b/stdlib/Cargo.toml index 4db773c57a..9119690d14 100644 --- a/stdlib/Cargo.toml +++ b/stdlib/Cargo.toml @@ -51,7 +51,7 @@ test-utils = { package = "miden-test-utils", path = "../test-utils" } vm-core = { package = "miden-core", path = "../core", version = "0.11", default-features = false } winter-air = { package = "winter-air", version = "0.11" } winter-fri = { package = "winter-fri", version = "0.11" } -winter-crypto = { package = "winter-crypto", version = "0.13" } +winter-crypto = { package = "winter-crypto", version = "0.12" } rand_chacha = { version = "0.3", default-features = false } diff --git a/stdlib/tests/crypto/stark/mod.rs b/stdlib/tests/crypto/stark/mod.rs index 7b2527822b..2bd5f83457 100644 --- a/stdlib/tests/crypto/stark/mod.rs +++ b/stdlib/tests/crypto/stark/mod.rs @@ -18,8 +18,12 @@ mod signature; #[test] fn signature_verification() { - let VerifierData { initial_stack, tape, store, advice_map } = - generate_signature_data().unwrap(); + let VerifierData { + initial_stack, + advice_stack: tape, + store, + advice_map, + } = generate_signature_data().unwrap(); let source = " use.std::crypto::dsa::rpo_stark::verifier diff --git a/stdlib/tests/crypto/stark/signature/mod.rs b/stdlib/tests/crypto/stark/signature/mod.rs index 7c37efce56..f38d187a98 100644 --- a/stdlib/tests/crypto/stark/signature/mod.rs +++ b/stdlib/tests/crypto/stark/signature/mod.rs @@ -18,7 +18,7 @@ pub type QuadExt = QuadExtension; #[derive(Debug, Clone, Eq, PartialEq)] pub struct VerifierData { pub initial_stack: Vec, - pub tape: Vec, + pub advice_stack: Vec, pub store: MerkleStore, pub advice_map: Vec<(RpoDigest, Vec)>, } @@ -168,7 +168,7 @@ pub fn generate_advice_inputs_signature( Ok(VerifierData { initial_stack, - tape, + advice_stack: tape, store, advice_map: main_aux_adv_map, }) From 5504f7fa0d0dd2020722952c0e1f625c7b796737 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:35:59 +0100 Subject: [PATCH 16/19] chore: refactored verifier data in tests --- Cargo.lock | 96 +++++++++++-------- core/Cargo.toml | 3 +- prover/src/lib.rs | 2 - stdlib/Cargo.toml | 2 +- stdlib/tests/crypto/stark/mod.rs | 13 ++- stdlib/tests/crypto/stark/signature/mod.rs | 10 +- .../crypto/stark/verifier_recursive/mod.rs | 10 +- 7 files changed, 70 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c79fed586..add59a2790 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1046,15 +1046,15 @@ dependencies = [ "num-traits", "parking_lot", "proptest", - "winter-math 0.11.0", + "winter-math", "winter-rand-utils", - "winter-utils 0.11.0", + "winter-utils", ] [[package]] name = "miden-crypto" -version = "0.12.0" -source = "git+https://github.com/0xPolygonMiden/crypto?branch=al-stark-signature-dev-masm#866fda603af0ccdd8534df7d297ca9099bcc660c" +version = "0.13.0" +source = "git+https://github.com/0xPolygonMiden/crypto?branch=al-stark-signature-dev-masm#c41b45f3bda4b31b836a86865861e0b1ad8f31ed" dependencies = [ "blake3", "cc", @@ -1065,9 +1065,16 @@ dependencies = [ "rand_chacha", "rand_core", "sha3", - "winter-crypto 0.10.2", - "winter-math 0.10.2", - "winter-utils 0.10.2", + "thiserror 2.0.3", + "winter-air", + "winter-crypto", + "winter-fri", + "winter-math", + "winter-maybe-async", + "winter-prover", + "winter-utils", + "winter-verifier", + "winterfell", ] [[package]] @@ -1087,7 +1094,7 @@ checksum = "04742d5184bd76e7b92afcd9ca36b7c587a555d5fc4b27bb8f9d64ac57151f9c" dependencies = [ "metal", "once_cell", - "winter-math 0.11.0", + "winter-math", ] [[package]] @@ -1144,7 +1151,7 @@ dependencies = [ "tracing", "winter-fri", "winter-prover", - "winter-utils 0.11.0", + "winter-utils", ] [[package]] @@ -1703,7 +1710,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2144,7 +2151,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] @@ -2158,6 +2174,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.8" @@ -2261,7 +2288,7 @@ checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" dependencies = [ "ansi_term", "smallvec", - "thiserror", + "thiserror 1.0.69", "tracing", "tracing-subscriber", ] @@ -2751,10 +2778,10 @@ version = "0.11.0" source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "libm", - "winter-crypto 0.11.0", + "winter-crypto", "winter-fri", - "winter-math 0.11.0", - "winter-utils 0.11.0", + "winter-math", + "winter-utils", ] [[package]] @@ -2766,8 +2793,8 @@ dependencies = [ "rand", "rand_chacha", "sha3", - "winter-math 0.11.0", - "winter-utils 0.11.0", + "winter-math", + "winter-utils", ] [[package]] @@ -2778,17 +2805,8 @@ dependencies = [ "rand", "rand_chacha", "winter-crypto", - "winter-math 0.11.0", - "winter-utils 0.11.0", -] - -[[package]] -name = "winter-math" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82479f94efc0b5374a93e2074ba46ef404384fb1ea6e35a847febec53096509b" -dependencies = [ - "winter-utils 0.10.2", + "winter-math", + "winter-utils", ] [[package]] @@ -2796,7 +2814,7 @@ name = "winter-math" version = "0.11.0" source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ - "winter-utils 0.11.0", + "winter-utils", ] [[package]] @@ -2817,12 +2835,12 @@ dependencies = [ "rand_chacha", "tracing", "winter-air", - "winter-crypto 0.11.0", + "winter-crypto", "winter-fri", - "winter-math 0.11.0", + "winter-math", "winter-maybe-async", "winter-rand-utils", - "winter-utils 0.11.0", + "winter-utils", ] [[package]] @@ -2831,15 +2849,9 @@ version = "0.11.0" source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "rand", - "winter-utils 0.11.0", + "winter-utils", ] -[[package]] -name = "winter-utils" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f948e71ffd482aa13d0ec3349047f81ecdb89f3b3287577973dcbf092a25fb4" - [[package]] name = "winter-utils" version = "0.11.0" @@ -2854,10 +2866,10 @@ version = "0.11.0" source = "git+https://github.com/Al-Kindi-0/winterfell?branch=al-zk#606ffe7344aa165a5b58053cf678a5fb4f27ebcb" dependencies = [ "winter-air", - "winter-crypto 0.11.0", + "winter-crypto", "winter-fri", - "winter-math 0.11.0", - "winter-utils 0.11.0", + "winter-math", + "winter-utils", ] [[package]] diff --git a/core/Cargo.toml b/core/Cargo.toml index adc6d22958..8643a81ba9 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -34,8 +34,7 @@ std = [ lock_api = { version = "0.4", features = ["arc_lock"] } math = { package = "winter-math", version = "0.11", default-features = false } memchr = { version = "2.7", default-features = false } -#miden-crypto = { version = "0.13", default-features = false } -miden-crypto = { git = "https://github.com/0xPolygonMiden/crypto/", branch ="al-fix-rpo-randcoin", default-features = false } +miden-crypto = { version = "0.13", default-features = false } miden-formatting = { version = "0.1", default-features = false } miette = { package = "miden-miette", version = "7.1", default-features = false, optional = true, features = [ "fancy-no-syscall", diff --git a/prover/src/lib.rs b/prover/src/lib.rs index dc39868e8b..3adbcc5f38 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -193,8 +193,6 @@ where DefaultConstraintCommitment; type ConstraintEvaluator<'a, E: FieldElement> = DefaultConstraintEvaluator<'a, ProcessorAir, E>; - type ConstraintCommitment> = - DefaultConstraintCommitment; type ZkPrng = MockPrng; fn options(&self) -> &WinterProofOptions { diff --git a/stdlib/Cargo.toml b/stdlib/Cargo.toml index 9119690d14..47fba74a9e 100644 --- a/stdlib/Cargo.toml +++ b/stdlib/Cargo.toml @@ -51,7 +51,7 @@ test-utils = { package = "miden-test-utils", path = "../test-utils" } vm-core = { package = "miden-core", path = "../core", version = "0.11", default-features = false } winter-air = { package = "winter-air", version = "0.11" } winter-fri = { package = "winter-fri", version = "0.11" } -winter-crypto = { package = "winter-crypto", version = "0.12" } +winter-crypto = { package = "winter-crypto", version = "0.11" } rand_chacha = { version = "0.3", default-features = false } diff --git a/stdlib/tests/crypto/stark/mod.rs b/stdlib/tests/crypto/stark/mod.rs index 2bd5f83457..343bc37b71 100644 --- a/stdlib/tests/crypto/stark/mod.rs +++ b/stdlib/tests/crypto/stark/mod.rs @@ -1,9 +1,9 @@ use assembly::Assembler; use miden_air::{FieldExtension, HashFunction, PublicInputs}; -use processor::{DefaultHost, Program, ProgramInfo}; +use processor::{crypto::MerkleStore, DefaultHost, Digest, Program, ProgramInfo}; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; -use signature::{generate_advice_inputs_signature, VerifierData}; +use signature::generate_advice_inputs_signature; use test_utils::{ crypto::rpo_stark::{PublicInputs as SignaturePublicInputs, SecretKey}, prove, @@ -13,6 +13,7 @@ use test_utils::{ mod verifier_recursive; use verifier_recursive::generate_advice_inputs; +use vm_core::Felt; mod signature; @@ -114,3 +115,11 @@ pub fn generate_recursive_verifier_data( let (_, proof) = proof.into_parts(); Ok(generate_advice_inputs(proof, pub_inputs).unwrap()) } + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct VerifierData { + pub initial_stack: Vec, + pub advice_stack: Vec, + pub store: MerkleStore, + pub advice_map: Vec<(Digest, Vec)>, +} diff --git a/stdlib/tests/crypto/stark/signature/mod.rs b/stdlib/tests/crypto/stark/signature/mod.rs index f38d187a98..9e9f7044ab 100644 --- a/stdlib/tests/crypto/stark/signature/mod.rs +++ b/stdlib/tests/crypto/stark/signature/mod.rs @@ -12,17 +12,11 @@ use winter_fri::VerifierChannel as FriVerifierChannel; mod channel; use channel::VerifierChannel; +use super::VerifierData; + pub const BLOWUP_FACTOR: usize = 8; pub type QuadExt = QuadExtension; -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct VerifierData { - pub initial_stack: Vec, - pub advice_stack: Vec, - pub store: MerkleStore, - pub advice_map: Vec<(RpoDigest, Vec)>, -} - pub fn generate_advice_inputs_signature( proof: Proof, pub_inputs: ::PublicInputs, diff --git a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs index 2ffe72c987..49030ae671 100644 --- a/stdlib/tests/crypto/stark/verifier_recursive/mod.rs +++ b/stdlib/tests/crypto/stark/verifier_recursive/mod.rs @@ -13,19 +13,11 @@ use winter_fri::VerifierChannel as FriVerifierChannel; mod channel; use channel::VerifierChannel; -use super::signature::VerifierData; +use super::VerifierData; pub const BLOWUP_FACTOR: usize = 8; pub type QuadExt = QuadExtension; -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct VerifierData { - pub initial_stack: Vec, - pub advice_stack: Vec, - pub store: MerkleStore, - pub advice_map: Vec<(RpoDigest, Vec)>, -} - pub fn generate_advice_inputs( proof: Proof, pub_inputs: ::PublicInputs, From d2315405feda9a3604a41456e4a8882c98f49468 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:04:43 +0100 Subject: [PATCH 17/19] chore: remove duplicate procedures --- .../crypto/dsa/rpo_stark/deep_queries.masm | 129 +----- .../asm/crypto/dsa/rpo_stark/random_coin.masm | 409 +----------------- stdlib/asm/crypto/dsa/rpo_stark/utils.masm | 2 +- stdlib/asm/crypto/dsa/rpo_stark/verifier.masm | 3 +- stdlib/asm/crypto/stark/random_coin.masm | 1 - 5 files changed, 16 insertions(+), 528 deletions(-) diff --git a/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm b/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm index 43f8f5d6fb..ced8ecae27 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/deep_queries.masm @@ -1,128 +1,5 @@ use.std::crypto::dsa::rpo_stark::constants - -#! Computes a single step of the random linear combination defining the DEEP composition polynomial -#! that is the input to the FRI protocol. More precisely, the sum in question is: -#! $$ -#! \sum_{i=0}^k{\alpha_i \cdot \left(\frac{T_i(x) - T_i(z)}{x - z} + -#! \frac{T_i(x) - T_i(z \cdot g)}{x - z \cdot g} \right)} -#! $$ -#! -#! and the following instruction computes the denominators $\alpha_i \cdot (T_i(x) - T_i(z))$ and -#! $\alpha_i \cdot (T_i(x) - T_i(z \cdot g))$ and stores the values in two accumulators $r$ and $p$, -#! respectively. This instruction is specialized to auxiliary trace columns i.e. the values $T_i(x)$ -#! are field elements in a quadratic extension field. -#! -#! The stack transition of the instruction can be visualized as follows: -#! -#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+------+------+---+ -#! | T31 | T30 | T21 | T20 | T11 | T10 | T01 | T00 | p1 | p0 | r1 | r0 |x_addr|z_addr|a_addr| - | -#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+------+------+---+ -#! -#! || -#! \/ -#! -#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+--------+--------+-----+ -#! | T31 | T30 | T21 | T20 | T11 | T10 | T01 | T00 | p1' | p0' | r1' | r0' |x_addr|z_addr+1|a_addr+b| - | -#! +-------+-------+-------+-------+-------+-------+-------+-------+------+------+------+------+------+--------+--------------+ -#! -#! -#! Here: -#! 1- Tij for i in 0..=3 and j=0,1 stands for the the value of the j-th coordinate in the quadratic extension field -#! of the i-th auxiliary trace polynomial for the current query i.e. $T_i(x)$. -#! 2- (p0, p1) stands for an extension field element accumulating the values for the quotients with common denominator (x - gz). -#! 3- (r0, r1) stands for an extension field element accumulating the values for the quotients with common denominator (x - z). -#! 4- x_addr is the memory address from which we are loading the Ti's using the MSTREAM instruction. -#! 5- z_addr is the memory address to the i-th OOD evaluation frame at z and gz i.e. T_i(z):= (T_i(z)0, T_i(z)1) and T_i(gz):= (T_i(gz)0, T_i(gz)1) -#! 6- a_addr is the memory address of the i-th random element used in batching the trace polynomial quotients. -#! The random elements a := (a0, a1) are stored in memory as [0, 0, a0, a1]. -#! -#! Input: [T31, T30, T21, T20, T11, T10, T01, T00, p1, p0, r1, r0, x_addr, z_addr, a_addr, 0] -#! Output: [T01, T00, T31, T30, T21, T20, T11, T10, p1', p0', r1', r0', x_addr, z_addr', a_addr', 0] -export.combine_aux - - # 1) Shift trace columns values (as quadratic extension field element) left - movup.7 movup.7 - #=> [T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr, a_addr, 0] - - # 2) Get a_addr and update it. This is done here before it becomes inaccessible. - - # Update a_addr - dup.14 add.1 swap.15 - #=> [a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr, a_addr', 0] - - # 3) Load i-th OOD frame portion. This assumes that the OOD frame has been serialized with `current` and `next` rows interleaved. - # This also updates the z_addr pointer. - dup.14 add.1 swap.15 - padw movup.4 mem_loadw - #=> [Tgz1, Tgz0, Tz1, Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # 4) Compute the numerators - - # a) Compute T_i - T_i(z). This equals, in the case of T0, (T01 - Tz1, T00 - Tz0) - dup.6 dup.6 - movup.5 movup.5 - #=> [Tz1, Tz0, T01, T00, Tgz1, Tgz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - ext2sub - #=> [T01 - Tz1, T00 - Tz0, Tgz1, Tgz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - movdn.3 movdn.3 - #=> [Tgz1, Tgz0, T01 - Tz1, T00 - Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # b) Compute T_i - T_i(gz). This equals, in the case of T0, (T01 - Tgz1, T00 - Tgz0) - - # Compute first -(T_i - T_i(gz)) - dup.6 dup.6 - ext2sub - #=> [Tgz1 - T01, Tgz0 - T00, T01 - Tz1, T00 - Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # Negate both coordinates - neg swap neg swap - #=> [T01 - Tgz1, T00 - Tgz0, T01 - Tz1, T00 - Tz0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - #=> [Δg1, Δg0, Δ1, Δ0, a_addr, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - # where Δg1 := T01 - Tgz1, Δg0 := T00 - Tgz0, Δ1 := T01 - Tz1 and Δ0 := T00 - Tz0 - - # 5) Multiply by randomness - - # a) Load randomness from memory - padw - movup.8 mem_loadw drop drop - #=> [a1', a0', a1, a0, Δg1, Δg0, Δ1, Δ0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # b) Multiply (Δ0, Δ1) - dup.1 dup.1 - movup.7 movup.7 - #=> [Δ1, Δ0, a1, a0, a1, a0, Δg1, Δg0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - ext2mul - #=> [prod1, prod0, a1, a0, Δg1, Δg0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - # where (prod0, prod1) := (Δ0, Δ1) * (a0, a1) - - movdn.5 movdn.5 - #=> [a1, a0, Δg1, Δg0, prod1, prod0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - - # c) Multiply (Δg0, Δg1) - ext2mul - #=> [prodg1, prodg0, prod1, prod0, T01, T00, T31, T30, T21, T20, T11, T10, p1, p0, r1, r0, x_addr, z_addr', a_addr', 0] - # where (prodg0, prodg1) := (Δg0, Δg1) * (a0, a1) - - # 6) Accumulate into (p0, p1) and (r0, r1) - movupw.3 - - # a) Accumulate into (r0, r1) - movup.7 movup.7 - #=> [prod1, prod0, p1, p0, r1, r0, prodg1, prodg0, T01, T00, T31, T30, T21, T20, T11, T10, x_addr, z_addr', a_addr', 0] - movup.5 movup.5 ext2add - #=> [r1', r0', p1, p0, prodg1, prodg0, T01, T00, T31, T30, T21, T20, T11, T10, x_addr, z_addr', a_addr', 0] - - # b) Accumulate into (p0, p1) - movdn.5 movdn.5 ext2add - #=> [p1', p0', r1', r0', T01, T00, T31, T30, T21, T20, T11, T10, x_addr, z_addr', a_addr', 0] - - # c) Prepare for next iteration - movdnw.2 - #=> [T01, T00, T31, T30, T21, T20, T11, T10, p1', p0', r1', r0', x_addr, z_addr', a_addr', 0] -end +use.std::crypto::stark::deep_queries #! Loads the next query rows in the main, auxiliary and constraint composition polynomials traces. #! It takes a pointer to the current random query index and returns that index. @@ -333,12 +210,12 @@ proc.combine_constraint_poly_columns repeat.2 mem_stream repeat.4 - exec.combine_aux + exec.deep_queries::combine_aux end end mem_stream repeat.2 - exec.combine_aux + exec.deep_queries::combine_aux end # TODO: optimize this so as to keep the randomizer on the stack diff --git a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm index 63b4f5f90a..4363023762 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm @@ -1,34 +1,7 @@ use.std::crypto::dsa::rpo_stark::constants use.std::crypto::dsa::rpo_stark::utils use.std::crypto::hashes::rpo - - -#! Helper procedure to compute addition of two words component-wise. -#! Input: [b3, b2, b1, b0, a3, a2, a1, a0] -#! Output: [c3, c2, c1, c0] -#! -#! Cycles: 16 -proc.add_two_words - movup.3 - movup.7 - add - #=> [c0, b3, b2, b1, a3, a2, a1] - - movup.3 - movup.6 - add - #=> [c1, c0, b3, b2, a3, a2] - - movup.3 - movup.5 - add - #=> [c2, c1, c0, b3, a3] - - movup.3 - movup.4 - add - #=> [c3, c2, c1, c0] -end +use.std::crypto::stark::random_coin #! Return the first half of the rate portion of the random coin state #! @@ -144,7 +117,7 @@ export.reseed exec.get_rate_1 # => [R1, DATA, ...] (6 cycles) - exec.add_two_words + exec.random_coin::add_two_words # => [R1, ...] (16 cycles) exec.get_capacity @@ -177,14 +150,14 @@ export.reseed_with_salt exec.get_rate_1 # => [R1, DATA, ...] (6 cycles) - exec.add_two_words + exec.random_coin::add_two_words # => [R1, ...] (16 cycles) exec.get_capacity swapw exec.get_rate_2 padw adv_loadw - exec.add_two_words + exec.random_coin::add_two_words # => [R2, R1, C, ...] (30 cycles) hperm @@ -211,7 +184,7 @@ end export.generate_constraint_composition_coefficients push.24 swap - exec.generate_random_coefficients + exec.random_coin::generate_random_coefficients #=> [...] end @@ -229,202 +202,10 @@ end export.generate_deep_composition_random_coefficients push.24 swap - exec.generate_random_coefficients_pad - #=> [...] -end - - -# COEFFICIENT GENERATION -# ============================================================================================= - -#! Generates a `num_tuples` tuples of random field elements and stores them in memory -#! starting from address `dest_ptr`. Each memory address holds two tuples. -#! TODO: Generalize by keeping track of something similar to the `output` variable in `RpoRandomCoin` -#! so that we keep track of already used randomness and know when there is a need to apply `hperm`. -#! -#! Input: [dest_ptr, num_tuples, ...] -#! Output: [...] -#! -#! Cycles: 69 + (22 * num_tuples) / 4 -proc.generate_random_coefficients - - # Compute the loop counter. We use checked division to make sure the number is a multiple of 4. - # If we use field division and num_tuples is not a multiple of 4 then we will enter into - # a very large loop with high probability. - push.0 dup movup.2 movup.3 - u32assert u32divmod.4 - assertz - neg - #=> [loop_ctr, dest_ptr, x, x, ...] - # where loop_ctr = - num_tuples / 4; we negate the counter so that we can count up to 0 - - exec.get_rate_1 - dup.5 mem_storew - - exec.get_rate_2 - dup.9 add.1 mem_storew - #=> [R2, R1, loop_ctr, dest_ptr, 0, 0, ..] - - exec.get_capacity - swapdw - swapw - swap add.2 swap - #=> [loop_ctr, dest_ptr, 0, 0, R1, C, R2, ..] - - add.1 dup neq.0 - - while.true - - swapw.3 hperm - #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] - - # save R2 to mem[dest+1]; we use dup.13 here because it takes only 1 cycle - dup.13 add.1 mem_storew - #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] - - # save R1 to mem[dest] - swapw dup.13 mem_storew swapw - #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] - - # update destination pointer and loop counter - swapw.3 - #=> [loop_ctr, dest_ptr, x, x, R1, C, R2, ...] - - swap add.2 swap - #=> [loop_ctr, dest_ptr+2, x, x, R1, C, R2, ...] - - add.1 dup - #=> [loop_ctr+1, loop_ctr+1, dest_ptr+2, x, x, R1, C, R2, ...] - - neq.0 - end - - # Save the new state of the random coin - dropw - exec.constants::r1_ptr mem_storew - dropw - exec.constants::c_ptr mem_storew - dropw - exec.constants::r2_ptr mem_storew - dropw + exec.random_coin::generate_random_coefficients_pad #=> [...] end - -#! Generates a `num_tuples` tuples of random field elements and stores them in memory -#! starting from address `dest_ptr`. Each memory address holds one tuple. -#! TODO: Generalize by keeping track of something similar to the `output` variable in `RpoRandomCoin` -#! so that we keep track of already used randomness and know when there is a need to apply `hperm`. -#! -#! Input: [dest_ptr, num_tuples, ...] -#! Output: [...] -#! -#! Cycles: 104 + (69 * num_tuples) / 4 -proc.generate_random_coefficients_pad - - # Compute the loop counter. We use checked division to make sure the number is a multiple of 4. - # If we use field division and num_tuples is not a multiple of 4 then we will enter into - # a very large loop with high probability. - push.0 dup movup.2 movup.3 - u32assert u32divmod.4 - assertz - neg - #=> [loop_ctr, dest_ptr, x, x, ...] - # where loop_ctr = - num_tuples / 4; we negate the counter so that we can count up to 0 - - exec.get_rate_1 - dup.5 - #=> [dest_ptr, a11, a10, a01, a00, loop_ctr, dest_ptr, x, x, ...] - dup.4 - dup.4 - push.0.0 - dup.4 - mem_storew - #=> [0, 0, a01, a00, dest_ptr, a11, a10, a01, a00, loop_ctr, dest_ptr, x, x, ...] - - dropw - dup.2 dup.2 push.0.0 - movup.4 add.1 mem_storew - #=> [0, 0, a11, a10, a11, a10, a01, a00, loop_ctr, dest_ptr, x, x, ...] - - exec.constants::r2_ptr mem_loadw - dup.9 add.4 swap.10 - #=> [dest_ptr, a31, a30, a21, a20, a11, a10, a01, a00, loop_ctr, dest_ptr+4, x, x, ...] - - dup.4 - dup.4 - push.0.0 - dup.4 add.2 - mem_storew - #=> [0, 0, a21, a20, dest_ptr, a31, a30, a21, a20, a11, a10, a01, a00, loop_ctr, dest_ptr+4, x, x, ...] - dropw - dup.2 dup.2 push.0.0 - movup.4 add.3 mem_storew - #=> [0, 0, a31, a30, a31, a30, a21, a20, a11, a10, a01, a00, loop_ctr, dest_ptr+4, x, x, ...] - - exec.constants::c_ptr mem_loadw - swapdw - swapw - #=> [loop_ctr, dest_ptr, 0, 0, R1, C, R2, ..] - - add.1 dup neq.0 - - while.true - - swapw.3 hperm - #=> [R2, R1, C, loop_ctr, dest_ptr, x, x, ...] - - # save R2 to mem[dest+1]; we use dup.13 here because it takes only 1 cycle - dup.13 - dup.4 dup.4 push.0.0 - dup.4 add.2 - mem_storew - #=> [0, 0, a21, a20, dest_ptr, a31, a30, a21, a20, a11, a10, a01, a00, C, loop_ctr, dest_ptr, x, x, ...] - dropw - dup.2 dup.2 push.0.0 - movup.4 add.3 mem_storew - #=> [0, 0, a31, a30, a31, a30, a21, a20, a11, a10, a01, a00, C, loop_ctr, dest_ptr, x, x, ...] - - # save R1 to mem[dest] - dropw - swapw dup.13 - dup.4 dup.4 push.0.0 - dup.4 - mem_storew - #=> [0, 0, a01, a00, dest_ptr, a11, a10, a01, a00, a31, a30, a21, a20, C, loop_ctr, dest_ptr, x, x, ...] - dropw - dup.2 dup.2 push.0.0 - movup.4 add.1 mem_storew - #=> [0, 0, a01, a00, a11, a10, a01, a00, a31, a30, a21, a20, C, loop_ctr, dest_ptr, x, x, ...] - - # reshuffle and update destination pointer and loop counter - dropw - swapw - swapw.3 - #=> [loop_ctr, dest_ptr, x, x, R1, C, R2, ...] - - swap add.4 swap - #=> [loop_ctr, dest_ptr+2, x, x, R1, C, R2, ...] - - add.1 dup - #=> [loop_ctr+1, loop_ctr+1, dest_ptr+2, x, x, R1, C, R2, ...] - - neq.0 - end - - # Save the new state of the random coin - dropw - exec.constants::r1_ptr mem_storew - dropw - exec.constants::c_ptr mem_storew - dropw - exec.constants::r2_ptr mem_storew - dropw - #=> [...] -end - - - # OOD POINT GENERATION # ============================================================================================= @@ -474,130 +255,13 @@ export.generate_z_zN dropw end - - # INDEX GENERATION # ============================================================================================= -# Helper function for generating a list of indices that takes a word of random felts and saves -# to memory region referenced by `ptr` 4 random integers in the range 0..=(mask+1). -# `depth` is saved next to each of the 4 integers for use in subsequent steps. -# -# Input: [R, ptr, mask, depth, ...] -# Output:[...] -# -# Cycles: 100 -proc.generate_four_integers - # Get the first random felt - dup.3 # [r0, R1, ptr, mask, depth, ...] - u32split swap # [r0_lo, r0_hi, R1, ptr, mask, depth, ...] - dup.7 # [mask, r0_lo, r0_hi, R1, ptr, mask, depth, ...] - u32and # [r, r0_hi, R1, ptr, mask, depth, ...] - dup.8 swap # [r, depth, r0_hi, R1, ptr, mask, depth, ...] - push.0 movdn.3 # [r, depth, r0_hi, 0, R1, ptr, mask, depth, ...] - - # Store and update pointer - dup.8 add.1 swap.9 # [ptr, r, depth, r0_hi, 0, R1, ptr + 1, mask, depth, ...] - mem_storew - dropw # [R1, ptr + 1, mask, depth, ...] - - # Get the second random felt - dup.2 # [r1, R1, ptr, mask, depth, ...] - u32split swap # [r1_lo, r1_hi, R1, ptr, mask, depth, ...] - dup.7 # [mask, r1_lo, r1_hi, R1, ptr, mask, depth, ...] - u32and # [r, r1_hi, R1, ptr, mask, depth, ...] - dup.8 swap # [r, depth, r1_hi, R1, ptr, mask, depth, ...] - push.0 movdn.3 # [r, depth, r1_hi, 0, R1, ptr, mask, depth, ...] - - # Store and update pointer - dup.8 add.1 swap.9 # [ptr, r, depth, r1_hi, 0, R1, ptr + 1, mask, depth, ...] - mem_storew - dropw # [R1, ptr + 1, mask, depth, ...] - - # Get the third random felt - dup.1 - u32split swap - dup.7 - u32and - dup.8 swap - push.0 movdn.3 - - # Store and update pointer - dup.8 add.1 swap.9 - mem_storew - dropw - - # Get the fourth random felt - dup - u32split swap - dup.7 - u32and - dup.8 swap - push.0 movdn.3 - - # Store and update pointer - dup.8 add.1 swap.9 - mem_storew - dropw -end - -# Helper function for generating a list of indices. It takes a word of random felts and saves -# to a memory region, referenced by `ptr`, 3 random integers in the range 0..=(mask+1). This procedure -# is used to generate a list of random indices that are used in FRI. Moreover, this procedure -# is called first, and right after the PoW check, thus the first element in the rate portion of -# the state is discarded. -# `depth` is saved next to each of the 3 integers for use in subsequent steps. -# -# Input: [R, ptr, mask, depth, ...] -# Output:[R, ptr + 3, mask, depth, ...] -# -# Cycles: 75 -proc.generate_three_integers - # Get the second random felt - dup.2 # [r0, R1, ptr, mask, depth, ...] - u32split swap # [r0_lo, r0_hi, R1, ptr, mask, depth, ...] - dup.7 # [mask, r0_lo, r0_hi, R1, ptr, mask, depth, ...] - u32and # [r, r0_hi, R1, ptr, mask, depth, ...] - dup.8 swap # [r, depth, r0_hi, R1, ptr, mask, depth, ...] - push.0 movdn.3 # [r, depth, r0_hi, 0, R1, ptr, mask, depth, ...] - - # Store and update pointer - dup.8 add.1 swap.9 # [ptr, r, depth, r0_hi, 0, R1, ptr + 1, mask, depth, ...] - mem_storew - dropw # [R1, ptr + 1, mask, depth, ...] - - # Get the second random felt - dup.1 # [r1, R1, ptr, mask, depth, ...] - u32split swap # [r1_lo, r1_hi, R1, ptr, mask, depth, ...] - dup.7 # [mask, r1_lo, r1_hi, R1, ptr, mask, depth, ...] - u32and # [r, r1_hi, R1, ptr, mask, depth, ...] - dup.8 swap # [r, depth, r1_hi, R1, ptr, mask, depth, ...] - push.0 movdn.3 # [r, depth, r1_hi, 0, R1, ptr, mask, depth, ...] - - # Store and update pointer - dup.8 add.1 swap.9 # [ptr, r, depth, r1_hi, 0, R1, ptr + 1, mask, depth, ...] - mem_storew - dropw # [R1, ptr + 1, mask, depth, ...] - - # Get the third random felt - dup.0 - u32split swap - dup.7 - u32and - dup.8 swap - push.0 movdn.3 - - # Store and update pointer - dup.8 add.1 swap.9 - mem_storew - dropw -end - #! Generate a list of `num_queries` number of random indices in the range #! [0, lde_size] and store it in memory starting from `query_ptr`. #! The list is stored as `(r, depth, y, y)` where `depth` is `log(lde_domain_size)`. #!`depth` is needed when computing the deep queries. -#! TODO: the case of duplicate queries #! #! Input: [query_ptr, num_queries, ...] #! Output: [...] @@ -622,12 +286,12 @@ export.generate_list_indices # Load the first half of the rate portion of the state of the random coin. We discard the first # element as it is used for PoW and use the remaining the 3. exec.get_rate_1 - exec.generate_three_integers + exec.random_coin::generate_three_integers #=> [R, query_ptr, mask, depth, num_queries] # Load the second half of the rate portion of the state of the random coin. exec.constants::r2_ptr mem_loadw - exec.generate_four_integers + exec.random_coin::generate_four_integers #=> [R2, query_ptr, mask, depth, num_queries, ...] # Squeeze @@ -664,16 +328,14 @@ export.generate_list_indices #=> [quotient, X, query_ptr, mask, depth, remainder, ...] ## Use `quotient` to iterate - #add.1 dup movdn.8 - #push.777 movdn.8 #=> [quotient, X, query_ptr, mask, depth, quotient, remainder, ...] push.0 neq while.true - exec.generate_four_integers + exec.random_coin::generate_four_integers exec.constants::r2_ptr mem_loadw - exec.generate_four_integers + exec.random_coin::generate_four_integers #=> [R2, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] # Squeeze @@ -728,54 +390,3 @@ export.generate_list_indices dropw dropw dropw drop end - -# PROOF-OF-WORK CHECK -# ============================================================================================= - -#! Check that the Proof-of-Work contained in the nonce is equal to the required number -#! of bits prescribed by grinding bits. The grinding factor is assumed to be less than 32. -#! -#! Input: [grinding_factor, ...] -#! Output: [...] -#! Cycles: 73 -export.check_pow - # Compute the mask. - pow2 - u32assert u32overflowing_sub.1 assertz - #=> [mask, ...] - - # Load Capacity portion - exec.get_capacity - - # Load first half of rate portion and add pow witness to first element of rate - exec.get_rate_1 - adv_push.1 - dup.4 - add - swap.4 - drop - - # Load the second half of rate portion and apply the permutation - padw - exec.constants::r2_ptr mem_loadw - hperm - #=> [R2, R1, C, mask, ...] - - # Save the new random coin state - exec.constants::r2_ptr mem_storew - dropw - exec.constants::r1_ptr mem_storew - swapw - exec.constants::c_ptr mem_storew - dropw - drop drop drop - #=> [R10, mask] - - # Make sure the PoW is valid - u32split - drop - u32and - assertz - drop - #=> [...] -end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/utils.masm b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm index 112b76bf32..c4c1847aae 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/utils.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm @@ -77,7 +77,7 @@ end #! #! Input: [...] #! Output: [...] -#! Cycles: 1641 +#! Cycles: 3090 export.load_and_verify_remainder # Load remainder commitment and save it at `TMP1` padw diff --git a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm index 82cf88ab03..14cb8b86e8 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm @@ -5,6 +5,7 @@ use.std::crypto::dsa::rpo_stark::fri use.std::crypto::dsa::rpo_stark::random_coin use.std::crypto::dsa::rpo_stark::utils use.std::crypto::dsa::rpo_stark::constraints_evaluation +use.std::crypto::stark::random_coin->stark_random_coin # RPO-STARK-BASED SIGNATURE SCHEME VERIFICATION ALGORITHM @@ -140,7 +141,7 @@ export.verify #============================================ # Cycles: 73 - exec.random_coin::check_pow + exec.stark_random_coin::check_pow #=> [...] #============================================ diff --git a/stdlib/asm/crypto/stark/random_coin.masm b/stdlib/asm/crypto/stark/random_coin.masm index 63fe259c9f..70e059ffd5 100644 --- a/stdlib/asm/crypto/stark/random_coin.masm +++ b/stdlib/asm/crypto/stark/random_coin.masm @@ -625,7 +625,6 @@ end #! [0, lde_size] and store it in memory starting from `query_ptr`. #! The list is stored as `(r, depth, y, y)` where `depth` is `log(lde_domain_size)`. #!`depth` is needed when computing the deep queries. -#! TODO: the case of duplicate queries #! #! Input: [query_ptr, num_queries, ...] #! Output: [...] From 1ba8cf740c063472621c31768140787d435fd242 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:29:25 +0100 Subject: [PATCH 18/19] chore: refactor random index generation --- .../asm/crypto/dsa/rpo_stark/random_coin.masm | 136 ------------------ stdlib/asm/crypto/dsa/rpo_stark/utils.masm | 2 +- stdlib/asm/crypto/dsa/rpo_stark/verifier.masm | 4 +- stdlib/asm/crypto/stark/random_coin.masm | 12 +- stdlib/asm/crypto/stark/verifier.masm | 5 + 5 files changed, 13 insertions(+), 146 deletions(-) diff --git a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm index 4363023762..aa4f74372c 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/random_coin.masm @@ -254,139 +254,3 @@ export.generate_z_zN exec.constants::z_ptr mem_storew dropw end - -# INDEX GENERATION -# ============================================================================================= - -#! Generate a list of `num_queries` number of random indices in the range -#! [0, lde_size] and store it in memory starting from `query_ptr`. -#! The list is stored as `(r, depth, y, y)` where `depth` is `log(lde_domain_size)`. -#!`depth` is needed when computing the deep queries. -#! -#! Input: [query_ptr, num_queries, ...] -#! Output: [...] -#! -#! Cycles: 282 + q * 250 + r * 29 where q = num_queries / 8 and r = num_queries % 8 -#! -#! NOTE: This procedure is called first, and right after the PoW check, thus the first element -#! in the rate portion of the state is discarded. -#! NOTE: The cycle count can be estimated, using the fact that r < 8, via the more compact formula -#! 485 + 31 * num_queries -export.generate_list_indices - # push the depth - exec.constants::initial_lde_domain_log_size - # push the mask - exec.constants::initial_lde_domain_size sub.1 - #=> [mask, depth, query_ptr, num_queries] where depth = log(lde_size) - - # Get address holding the integers (this will later hold the FRI queries) - movup.2 - #=> [query_ptr, mask, depth, num_queries] - - # Load the first half of the rate portion of the state of the random coin. We discard the first - # element as it is used for PoW and use the remaining the 3. - exec.get_rate_1 - exec.random_coin::generate_three_integers - #=> [R, query_ptr, mask, depth, num_queries] - - # Load the second half of the rate portion of the state of the random coin. - exec.constants::r2_ptr mem_loadw - exec.random_coin::generate_four_integers - #=> [R2, query_ptr, mask, depth, num_queries, ...] - - # Squeeze - exec.constants::c_ptr mem_loadw - exec.get_rate_1 - exec.get_rate_2 - hperm - - # Save the new state - exec.constants::r2_ptr mem_storew - dropw - # => [R1, C] - exec.constants::r1_ptr mem_storew - swapw - # => [C, R1] - exec.constants::c_ptr mem_storew - dropw - #=> [R1, query_ptr, mask, depth, num_queries, ...] - - - # Use `num_queries` to iterate. - - ## Subtract the 7 elements we have already generated above. - movup.7 - push.7 sub - - ## Divide by 8 to get the number of iterations - u32assert u32divmod.8 - #=> [remainder, quotient, X, query_ptr, mask, depth, ...] - - - ## Save remainder for later use - movdn.8 - #=> [quotient, X, query_ptr, mask, depth, remainder, ...] - - ## Use `quotient` to iterate - dup movdn.8 - #=> [quotient, X, query_ptr, mask, depth, quotient, remainder, ...] - - push.0 neq - while.true - exec.random_coin::generate_four_integers - exec.constants::r2_ptr mem_loadw - exec.random_coin::generate_four_integers - #=> [R2, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] - - # Squeeze - exec.constants::c_ptr mem_loadw - exec.get_rate_1 - exec.get_rate_2 - hperm - - # Save the new state - exec.constants::r2_ptr mem_storew - dropw - # => [R1, C] - exec.constants::r1_ptr mem_storew - swapw - # => [C, R1] - exec.constants::c_ptr mem_storew - dropw - #=> [R1, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] - - movup.7 sub.1 dup movdn.8 - push.0 neq - end - #=> [R1, query_ptr, mask, depth, num_remaining_iterations, remainder, ...] - - ## Use remainder - - ### Put the remaining number of queries to generate in the appropriate stack position - movup.8 movdn.7 - - ### Load the second half of the rate portion of the state of the random coin. - padw exec.constants::r2_ptr mem_loadw - #=> [R2, R1, query_ptr, mask, depth, num_queries, ...] - - ### Iterate over remainder - dup.11 sub.1 swap.12 - neq.0 - while.true - movup.7 - u32split swap # [r0_lo, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] - dup.10 # [mask, r0_lo, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] - u32and # [r, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] - dup.11 swap # [r, depth, r0_hi, R2, r3, r2, r1, ptr, mask, depth, ...] - push.0 movdn.3 # [r, depth, r0_hi, 0, R2, r3, r2, r1, ptr, mask, depth, ...] - - # Store and update pointer - dup.11 add.1 swap.12 # [ptr, r, depth, r0_hi, 0, R2, r3, r2, r1, ptr + 1, mask, depth, ...] - mem_storew - drop drop drop # [x, R2, r3, r2, r1, ptr + 1, mask, depth, ...] - dup.11 sub.1 swap.12 - push.0 neq - end - - dropw dropw dropw drop -end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/utils.masm b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm index c4c1847aae..51ab4f40bd 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/utils.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/utils.masm @@ -141,4 +141,4 @@ export.load_and_verify_remainder # Drop pointers drop drop #=> [...] -end \ No newline at end of file +end diff --git a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm index 14cb8b86e8..ae3d3e1d7a 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/verifier.masm @@ -163,7 +163,9 @@ export.verify # # Cycles: 487 + 31 * num_queries swap dup.1 - exec.random_coin::generate_list_indices + exec.constants::initial_lde_domain_log_size + exec.constants::initial_lde_domain_size + exec.stark_random_coin::generate_list_indices #=> [query_ptr, ...] # Compute deep compostion polynomial queries diff --git a/stdlib/asm/crypto/stark/random_coin.masm b/stdlib/asm/crypto/stark/random_coin.masm index 70e059ffd5..2a392d427a 100644 --- a/stdlib/asm/crypto/stark/random_coin.masm +++ b/stdlib/asm/crypto/stark/random_coin.masm @@ -626,7 +626,7 @@ end #! The list is stored as `(r, depth, y, y)` where `depth` is `log(lde_domain_size)`. #!`depth` is needed when computing the deep queries. #! -#! Input: [query_ptr, num_queries, ...] +#! Input: [lde_domain_size, lde_domain_log_size, query_ptr, num_queries, ...] #! Output: [...] #! #! Cycles: 267 + q * 236 + r * 29 where q = num_queries / 8 and r = num_queries % 8 @@ -634,19 +634,15 @@ end #! NOTE: This procedure is called first, and right after the PoW check, thus the first element #! in the rate portion of the state is discarded. #! NOTE: The cycles count can be estimated, using the fact that r < 8, via the more compact formula -#! 470 + 236 * (num_queries / 8) +#! 485 + 31 * num_queries export.generate_list_indices # Create mask - padw - exec.constants::lde_size_ptr mem_loadw - movup.2 drop - movup.2 drop sub.1 - #=> [mask, depth, query_ptr, num_queries] where depth = log(lde_size) + #=> [mask, depth, query_ptr, num_queries, ...] where depth = log(lde_size) # Get address holding the integers (this will later hold the FRI queries) movup.2 - #=> [query_ptr, mask, depth, num_queries] + #=> [query_ptr, mask, depth, num_queries, ...] # Load the first half of the rate portion of the state of the random coin. We discard the first # element as it is used for PoW and use the remaining the 3. diff --git a/stdlib/asm/crypto/stark/verifier.masm b/stdlib/asm/crypto/stark/verifier.masm index edcc4adeca..53bb9a0651 100644 --- a/stdlib/asm/crypto/stark/verifier.masm +++ b/stdlib/asm/crypto/stark/verifier.masm @@ -216,6 +216,11 @@ export.verify # # Cycles: 470 + 236 * (num_queries / 8) swap dup.1 + #=> [query_ptr, num_queries, query_ptr, ...] + padw exec.constants::lde_size_ptr mem_loadw + movup.2 drop + movup.2 drop + #=> [lde_domain_size, lde_domain_log_size, query_ptr, num_queries, query_ptr, ...] exec.random_coin::generate_list_indices #=> [query_ptr, ...] From d29a02b7307ddc3bcbb60dca5cb70e8aac398680 Mon Sep 17 00:00:00 2001 From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:36:42 +0100 Subject: [PATCH 19/19] chore: remove use of magic constants --- stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm b/stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm index 5a7e9432fe..926064e4eb 100644 --- a/stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm +++ b/stdlib/asm/crypto/dsa/rpo_stark/constraints_evaluation.masm @@ -161,11 +161,11 @@ export.divide_transition_divisor # Multiply by (z - g^(8 - 1)) movdn.5 movdn.5 # => [z1, z0, tr_num1, tr_num0, z81, z80, ...] - swap add.1099511627520 swap ext2mul + swap exec.constants::minus_domain_gen_pow_7 add swap ext2mul # => [num1, num0, z81, z80, ...] # Divide by (z^8 - 1) - movup.3 add.18446744069414584320 movup.3 + movup.3 exec.constants::minus_one add movup.3 # => [den1, den0, num1, num0, ...] ext2div end