From d98a85855d9236f378d08c32c14ee1a6379400d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Masip?= Date: Mon, 18 Dec 2023 10:09:34 +0100 Subject: [PATCH 1/7] Starting the refactor with array add --- main/modexp/array_lib/array_add_AGTB.zkasm | 64 +++++++++------------ main/modexp/array_lib/array_add_short.zkasm | 33 +++++------ 2 files changed, 42 insertions(+), 55 deletions(-) diff --git a/main/modexp/array_lib/array_add_AGTB.zkasm b/main/modexp/array_lib/array_add_AGTB.zkasm index 3982aa5f..8e28339c 100644 --- a/main/modexp/array_lib/array_add_AGTB.zkasm +++ b/main/modexp/array_lib/array_add_AGTB.zkasm @@ -36,7 +36,7 @@ ; return result; ; } -; NOTE: It's unoptimized for the case where len(inB) = 1. Use array_add_short instead if possible. +; NOTE: It's unoptimized for the case where len(inB) = 1. Use array_add_short instead. VAR GLOBAL array_add_AGTB_inA[%ARRAY_MAX_LEN] VAR GLOBAL array_add_AGTB_inB[%ARRAY_MAX_LEN] @@ -60,71 +60,61 @@ array_add_AGTB: 0 => E ; index in loops 0 :MSTORE(array_add_AGTB_carry) - :JMP(array_add_AGTB_loopZero2inB) - -; Begin of branching -array_add_AGTB_add_carry1: - D + 1 => D :JMP(return_array_add_AGTB_add_carry1) - -array_add_AGTB_add_carry2: - D + 1 => D :JMP(return_array_add_AGTB_add_carry2) - -array_add_AGTB_add_carry3: - D + 1 => D :JMP(return_array_add_AGTB_add_carry3) -; End of branching array_add_AGTB_loopZero2inB: - 0 => D ; for the carry + ; The result will be stored as D·base + C + + 0 => D ; reset the carry chunk - ; a[i] + b[i] + ; a[i] + b[i], where a[i],b[i] ∈ [0,base-1]: This number cannot be GT base + (base - 2), two chunks $ => A :MLOAD(array_add_AGTB_inA + E) $ => B :MLOAD(array_add_AGTB_inB + E) - $ => C :ADD, JMPC(array_add_AGTB_add_carry1) - return_array_add_AGTB_add_carry1: + $ => C :ADD, JMPNC(__array_add_AGTB_continue_1) + 1 => D + __array_add_AGTB_continue_1: - ; sum = (a[i] + b[i]) + carry + ; sum = (a[i] + b[i]) + carry: This number cannot be GT base + (base - 1), two chunks $ => A :MLOAD(array_add_AGTB_carry) C => B - $ => C :ADD, JMPC(array_add_AGTB_add_carry2) - return_array_add_AGTB_add_carry2: + $ => C :ADD, JMPNC(__array_add_AGTB_continue_2) + 1 => D + __array_add_AGTB_continue_2: C :MSTORE(array_add_AGTB_out + E) D :MSTORE(array_add_AGTB_carry) - E + 1 => E - E => A + E + 1 => E,A $ => B :MLOAD(array_add_AGTB_len_inB) - $ :EQ, JMPC(array_add_AGTB_loop_index_check1, array_add_AGTB_loopZero2inB) + B - A :JMPZ(array_add_AGTB_loop_index_check, array_add_AGTB_loopZero2inB) -array_add_AGTB_loop_index_check1: - E => A +array_add_AGTB_loop_index_check: $ => B :MLOAD(array_add_AGTB_len_inA) - $ :EQ, JMPC(array_add_AGTB_check_carry) + B - A :JMPZ(array_add_AGTB_check_carry) + 0 => D array_add_AGTB_loopInB2InA: - ; sum = a[i] + carry + ; sum = a[i] + carry: This number cannot be GT base, two chunks $ => A :MLOAD(array_add_AGTB_inA + E) $ => B :MLOAD(array_add_AGTB_carry) - $ => C :ADD, JMPC(array_add_AGTB_add_carry3) - return_array_add_AGTB_add_carry3: + $ => C :ADD, JMPNC(__array_add_AGTB_continue_3) + 1 => D + __array_add_AGTB_continue_3: C :MSTORE(array_add_AGTB_out + E) D :MSTORE(array_add_AGTB_carry) - E + 1 => E - E => A + E + 1 => E,A $ => B :MLOAD(array_add_AGTB_len_inA) - $ :EQ, JMPC(array_add_AGTB_check_carry, array_add_AGTB_loopInB2InA) + B - A :JMPZ(array_add_AGTB_check_carry, array_add_AGTB_loopInB2InA) array_add_AGTB_check_carry: - $ => A :MLOAD(array_add_AGTB_carry) - 1 => B - $ :EQ, JMPNC(array_add_AGTB_len_out) + D => A + A :JMPZ(__array_add_AGTB_continue_4) + ; In this case, the carry = 1 and we should append it to the result 1 :MSTORE(array_add_AGTB_out + E) E + 1 :MSTORE(array_add_AGTB_len_out) :JMP(array_add_AGTB_end) - -array_add_AGTB_len_out: + __array_add_AGTB_continue_4: E :MSTORE(array_add_AGTB_len_out) array_add_AGTB_end: diff --git a/main/modexp/array_lib/array_add_short.zkasm b/main/modexp/array_lib/array_add_short.zkasm index 04d2bd42..cbb05c66 100644 --- a/main/modexp/array_lib/array_add_short.zkasm +++ b/main/modexp/array_lib/array_add_short.zkasm @@ -48,40 +48,37 @@ array_add_short: 0 => E ; index in loops $ => A :MLOAD(array_add_short_inB) A :MSTORE(array_add_short_carry) - :JMP(array_add_short_loopZero2inA) - -; Begin of branching -array_add_short_add_carry: - D + 1 => D :JMP(return_array_add_short_add_carry) -; End of branching array_add_short_loopZero2inA: - 0 => D ; for the carry + ; The result will be stored as D·base + C + + 0 => D ; reset the carry chunk - ; a[i] + carry. If i = 0, then carry = inB. + ; a[i] + carry, where a[i] ∈ [0,base-1]: + ; · If i = 0, then carry = inB and then the number cannot be GT base + (base - 2), two chunks + ; · Otherwise, the number cannot be GT base, two chunks $ => A :MLOAD(array_add_short_inA + E) $ => B :MLOAD(array_add_short_carry) - $ => C :ADD, JMPC(array_add_short_add_carry) - return_array_add_short_add_carry: + $ => C :ADD, JMPNC(__array_add_short_continue1) + 1 => D + __array_add_short_continue1: C :MSTORE(array_add_short_out + E) D :MSTORE(array_add_short_carry) - E + 1 => E - E => A + E + 1 => E,A $ => B :MLOAD(array_add_short_len_inA) - $ :EQ, JMPC(array_add_short_check_carry, array_add_short_loopZero2inA) + B - A :JMPZ(array_add_short_check_carry, array_add_short_loopZero2inA) array_add_short_check_carry: D => A - 1 => B - $ :EQ, JMPNC(array_add_short_len_out) + A :JMPZ(__array_add_short_continue2) + ; In this case, the carry = 1 and we should append it to the result 1 :MSTORE(array_add_short_out + E) E + 1 :MSTORE(array_add_short_len_out) :JMP(array_add_short_end) - -array_add_short_len_out: - E :MSTORE(array_add_short_len_out) + __array_add_short_continue2: + E :MSTORE(array_add_short_len_out) array_add_short_end: $ => RR :MLOAD(array_add_short_RR) From ec8a2c200d656e2f819723e803c9494a0bd5ca38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Masip?= Date: Mon, 18 Dec 2023 19:39:11 +0100 Subject: [PATCH 2/7] WIP --- main/modexp/array_lib/array_add_short.zkasm | 8 +- main/modexp/array_lib/array_div.zkasm | 79 ++++++-------- main/modexp/array_lib/array_div_long.zkasm | 102 ++++++++---------- main/modexp/array_lib/array_div_short.zkasm | 51 ++++----- main/modexp/array_lib/array_mul.zkasm | 1 + main/modexp/array_lib/array_mul_long.zkasm | 1 + main/modexp/array_lib/array_mul_short.zkasm | 1 + main/modexp/array_lib/array_square.zkasm | 1 + .../array_lib/unused/array_is_one.zkasm | 4 +- .../array_lib/unused/array_is_zero.zkasm | 4 +- main/modexp/modexp.zkasm | 12 +-- 11 files changed, 113 insertions(+), 151 deletions(-) diff --git a/main/modexp/array_lib/array_add_short.zkasm b/main/modexp/array_lib/array_add_short.zkasm index cbb05c66..a4717ca5 100644 --- a/main/modexp/array_lib/array_add_short.zkasm +++ b/main/modexp/array_lib/array_add_short.zkasm @@ -59,9 +59,9 @@ array_add_short_loopZero2inA: ; · Otherwise, the number cannot be GT base, two chunks $ => A :MLOAD(array_add_short_inA + E) $ => B :MLOAD(array_add_short_carry) - $ => C :ADD, JMPNC(__array_add_short_continue1) + $ => C :ADD, JMPNC(__array_add_short_continue_1) 1 => D - __array_add_short_continue1: + __array_add_short_continue_1: C :MSTORE(array_add_short_out + E) D :MSTORE(array_add_short_carry) @@ -72,12 +72,12 @@ array_add_short_loopZero2inA: array_add_short_check_carry: D => A - A :JMPZ(__array_add_short_continue2) + A :JMPZ(__array_add_short_continue_2) ; In this case, the carry = 1 and we should append it to the result 1 :MSTORE(array_add_short_out + E) E + 1 :MSTORE(array_add_short_len_out) :JMP(array_add_short_end) - __array_add_short_continue2: + __array_add_short_continue_2: E :MSTORE(array_add_short_len_out) array_add_short_end: diff --git a/main/modexp/array_lib/array_div.zkasm b/main/modexp/array_lib/array_div.zkasm index 2bada0d5..2e22d4ff 100644 --- a/main/modexp/array_lib/array_div.zkasm +++ b/main/modexp/array_lib/array_div.zkasm @@ -56,42 +56,36 @@ array_div: %MAX_CNT_STEPS - STEP - 19 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_div_RR) + C :MSTORE(array_div_len_inA) D :MSTORE(array_div_len_inB) ; Let's cover the edge cases - ; 1] Is C == 1 and inA == 0? - C => A 1 => B - $ :EQ, JMPNC(array_div_inA_continue) - 0 => B + ; 1] Is C == 1 and inA == 0? + C - B :JMPNZ(__array_div_inA_continue) $ => A :MLOAD(array_div_inA) - $ :EQ, JMPC(array_div_inA_is_zero) - array_div_inA_continue: + $ :LT, JMPC(array_div_inA_is_zero) + __array_div_inA_continue: ; 2] Is D == 1 and inB == 0? - D => A - 1 => B - $ :EQ, JMPNC(array_div_inB_continue1) - 0 => B + D - B :JMPNZ(__array_div_inB_continue_1) $ => A :MLOAD(array_div_inB) - $ :EQ, JMPC(array_div_inB_is_zero) - array_div_inB_continue1: + $ :LT, JMPC(array_div_inB_is_zero) + __array_div_inB_continue_1: ; 3] Check if inA = inB or inA < inB - C => RR - D => E + C - 1 => RR + D - 1 => E array_div_compare_inA: - RR - 1 => RR $ => A :MLOAD(array_div_inA + RR) A :MSTORE(array_compare_inA + RR) - RR :JMPZ(array_div_compare_inB, array_div_compare_inA) + RR - 1 => RR :JMPN(array_div_compare_inB, array_div_compare_inA) array_div_compare_inB: - E - 1 => E $ => A :MLOAD(array_div_inB + E) A :MSTORE(array_compare_inB + E) - E :JMPZ(array_div_compare, array_div_compare_inB) + E - 1 => E :JMPN(array_div_compare, array_div_compare_inB) array_div_compare: :CALL(array_compare) @@ -100,25 +94,20 @@ array_div_compare: %MAX_CNT_STEPS - STEP - 7 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) $ => A :MLOAD(array_compare_result), JMPZ(array_div_prep_inALTinB) - 1 => B - $ :EQ, JMPC(array_div_same_input) + A - 1 :JMPZ(array_div_same_input) ; From here, inA > inB - C => RR - D => A,E - 1 => B - $ :EQ, JMPC(array_div_inA_to_div_short, array_div_inA_to_div_long); worst case is div long + C - 1 => RR + D - 1 => E + D - 1 :JMPZ(array_div_inA_to_div_short, array_div_inA_to_div_long); worst case is div long ; Begin of edge cases array_div_inA_is_zero: ;Is D == 1 and inB == 0? 0/0 is undefined - D => A - 1 => B - $ :EQ, JMPNC(array_div_inB_continue2) - 0 => B + D - B :JMPNZ(__array_div_inB_continue_2) $ => A :MLOAD(array_div_inB) - $ :EQ, JMPC(array_div_inB_is_zero) - array_div_inB_continue2: + $ :LT, JMPC(array_div_inB_is_zero) + __array_div_inB_continue_2: ; From here, inB != 0 ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1 @@ -145,13 +134,11 @@ array_div_prep_inALTinB: %MAX_CNT_STEPS - STEP - 1 - 4*C - 2 :JMPN(outOfCountersStep) - 0 => RR - + C - 1 => RR array_div_inALTinB: $ => A :MLOAD(array_div_inA + RR) A :MSTORE(array_div_rem + RR) - RR + 1 => RR - C - 1 => C :JMPNZ(array_div_inALTinB) + RR - 1 => RR :JMPN(array_div_inALTinB_before_end, array_div_inALTinB) array_div_inALTinB_before_end: 0 :MSTORE(array_div_quo) @@ -160,16 +147,14 @@ array_div_inALTinB_before_end: ; Long array_div_inA_to_div_long: - RR - 1 => RR $ => A :MLOAD(array_div_inA + RR) A :MSTORE(array_div_long_inA + RR) - RR :JMPZ(array_div_inB_to_div_long, array_div_inA_to_div_long) + RR - 1 => RR :JMPN(array_div_inB_to_div_long, array_div_inA_to_div_long) array_div_inB_to_div_long: - E - 1 => E $ => A :MLOAD(array_div_inB + E) A :MSTORE(array_div_long_inB + E) - E :JMPZ(array_div_compute_long, array_div_inB_to_div_long) + E - 1 => E :JMPN(array_div_compute_long, array_div_inB_to_div_long) array_div_compute_long: :CALL(array_div_long) @@ -180,29 +165,26 @@ array_div_compute_long: $ => D :MLOAD(array_div_long_len_rem) C :MSTORE(array_div_len_quo) D :MSTORE(array_div_len_rem) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*D - 2 :JMPN(outOfCountersStep) array_div_assign_long_quo: - RR - 1 => RR $ => A :MLOAD(array_div_long_quo + RR) A :MSTORE(array_div_quo + RR) - RR :JMPZ(array_div_assign_long_rem, array_div_assign_long_quo) + RR - 1 => RR :JMPN(array_div_assign_long_rem, array_div_assign_long_quo) array_div_assign_long_rem: - E - 1 => E $ => A :MLOAD(array_div_long_rem + E) A :MSTORE(array_div_rem + E) - E :JMPZ(array_div_end, array_div_assign_long_rem) + E - 1 => E :JMPN(array_div_end, array_div_assign_long_rem) ; Short array_div_inA_to_div_short: - RR - 1 => RR $ => A :MLOAD(array_div_inA + RR) A :MSTORE(array_div_short_inA + RR) - RR :JMPZ(array_div_inB_to_div_short, array_div_inA_to_div_short) + RR - 1 => RR :JMPN(array_div_inB_to_div_short, array_div_inA_to_div_short) array_div_inB_to_div_short: $ => A :MLOAD(array_div_inB) @@ -216,15 +198,14 @@ array_div_compute_short: $ => C :MLOAD(array_div_short_len_quo) C :MSTORE(array_div_len_quo) 1 :MSTORE(array_div_len_rem) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 4 :JMPN(outOfCountersStep) array_div_assign_short_quo: - RR - 1 => RR $ => A :MLOAD(array_div_short_quo + RR) A :MSTORE(array_div_quo + RR) - RR :JMPZ(array_div_assign_short_rem, array_div_assign_short_quo) + RR - 1 => RR :JMPN(array_div_assign_short_rem, array_div_assign_short_quo) array_div_assign_short_rem: $ => A :MLOAD(array_div_short_rem) diff --git a/main/modexp/array_lib/array_div_long.zkasm b/main/modexp/array_lib/array_div_long.zkasm index c9792a7d..e3352750 100644 --- a/main/modexp/array_lib/array_div_long.zkasm +++ b/main/modexp/array_lib/array_div_long.zkasm @@ -54,42 +54,36 @@ array_div_long: %MAX_CNT_STEPS - STEP - 19 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_div_long_RR) + C :MSTORE(array_div_long_len_inA) D :MSTORE(array_div_long_len_inB) ; Let's cover the edge cases - ; 1] Is C == 1 and inA == 0? - C => A 1 => B - $ :EQ, JMPNC(array_div_long_inA_continue) - 0 => B + ; 1] Is C == 1 and inA == 0? + C - B :JMPNZ(__array_div_long_inA_continue) $ => A :MLOAD(array_div_long_inA) - $ :EQ, JMPC(array_div_long_inA_is_zero) - array_div_long_inA_continue: + $ :LT, JMPC(array_div_long_inA_is_zero) + __array_div_long_inA_continue: ; 2] Is D == 1 and inB == 0? - D => A - 1 => B - $ :EQ, JMPNC(array_div_long_inB_continue1) - 0 => B + D - B :JMPNZ(__array_div_long_inB_continue_1) $ => A :MLOAD(array_div_long_inB) - $ :EQ, JMPC(array_div_long_inB_is_zero) - array_div_long_inB_continue1: + $ :LT, JMPC(array_div_long_inB_is_zero) + __array_div_long_inB_continue_1: ; 3] Check if inA = inB or inA < inB - C => RR - D => E + C - 1 => RR + D - 1 => E array_div_long_compare_inA1: - RR - 1 => RR $ => A :MLOAD(array_div_long_inA + RR) A :MSTORE(array_compare_inA + RR) - RR :JMPZ(array_div_long_compare_inB1, array_div_long_compare_inA1) + RR - 1 => RR :JMPN(array_div_long_compare_inB1, array_div_long_compare_inA1) array_div_long_compare_inB1: - E - 1 => E $ => A :MLOAD(array_div_long_inB + E) A :MSTORE(array_compare_inB + E) - E :JMPZ(array_div_long_compare1, array_div_long_compare_inB1) + E - 1 => E :JMPN(array_div_long_compare1, array_div_long_compare_inB1) array_div_long_compare1: :CALL(array_compare) @@ -98,10 +92,10 @@ array_div_long_compare1: %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) $ => A :MLOAD(array_compare_result), JMPZ(array_div_long_prep_inALTinB) - 1 => B - $ :EQ, JMPC(array_div_long_same_input) + A - 1 :JMPZ(array_div_long_same_input) ; From here, inA > inB + ; Strategy: Divide outside and check the result inside $${MPdiv(addr.array_div_long_inA,mem.array_div_long_len_inA,addr.array_div_long_inB,mem.array_div_long_len_inB)} :JMP(array_div_long_prepare_mul_quo_inB) @@ -109,14 +103,11 @@ array_div_long_compare1: ; Begin of edge cases array_div_long_inA_is_zero: ; Is D == 1 and inB == 0? 0/0 is undefined - D => A - 1 => B - $ :EQ, JMPNC(array_div_long_inB_continue2) - 0 => B + D - B :JMPNZ(__array_div_long_inB_continue_2) $ => A :MLOAD(array_div_long_inB) - $ :EQ, JMPC(array_div_long_inB_is_zero) - array_div_long_inB_continue2: - ; From here, inB != 0 + $ :LT, JMPC(array_div_long_inB_is_zero) + __array_div_long_inB_continue_2: + ; From here, inA == 0 and inB != 0 ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1 0 :MSTORE(array_div_long_quo) @@ -130,6 +121,7 @@ array_div_long_inB_is_zero: 1 => B :JMP(array_div_long_end) array_div_long_same_input: + ; if inA = inB, then return [1, 0] and len(q) = 1, len(r) = 1 1 :MSTORE(array_div_long_quo) 0 :MSTORE(array_div_long_rem) 1 :MSTORE(array_div_long_len_quo) @@ -137,18 +129,17 @@ array_div_long_same_input: 0 => B :JMP(array_div_long_end) array_div_long_prep_inALTinB: - C :MSTORE(array_div_long_len_rem) + ; if inA < inB, then return [0, inA] and len(q) = 1, len(r) = C 1 :MSTORE(array_div_long_len_quo) + C :MSTORE(array_div_long_len_rem) %MAX_CNT_STEPS - STEP - 1 - 4*C - 2 :JMPN(outOfCountersStep) - 0 => RR - + C - 1 => RR array_div_long_inALTinB: $ => A :MLOAD(array_div_long_inA + RR) A :MSTORE(array_div_long_rem + RR) - RR + 1 => RR - C - 1 => C :JMPNZ(array_div_long_inALTinB) + RR - 1 => RR :JMPN(array_div_long_inALTinB_before_end, array_div_long_inALTinB) array_div_long_inALTinB_before_end: 0 :MSTORE(array_div_long_quo) @@ -171,24 +162,23 @@ array_div_long_prepare_mul_quo_inB: ; From here, the quotient is trimmed C :MSTORE(array_div_long_len_quo) + $ => D :MLOAD(array_div_long_len_inB) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 5*%ARRAY_MAX_LEN - 4*D - 1 :JMPN(outOfCountersStep) array_div_long_quo_to_mul: - RR - 1 => RR ${receiveQuotientChunk(RR)} => A A :MSTORE(array_div_long_quo + RR) A :MSTORE(array_mul_inA + RR) - RR :JMPZ(array_div_long_inB_to_mul, array_div_long_quo_to_mul) + RR - 1 => RR :JMPN(array_div_long_inB_to_mul, array_div_long_quo_to_mul) array_div_long_inB_to_mul: - E - 1 => E $ => A :MLOAD(array_div_long_inB + E) A :MSTORE(array_mul_inB + E) - E :JMPZ(array_div_long_mul_quo_inB, array_div_long_inB_to_mul) + E - 1 => E :JMPN(array_div_long_mul_quo_inB, array_div_long_inB_to_mul) array_div_long_mul_quo_inB: :CALL(array_mul) @@ -200,7 +190,7 @@ array_div_long_mul_quo_inB: $0{receiveLenRemainder()} => D ; 1] The received length must be between 1 and %ARRAY_MAX_LEN - D - 1 => E :JMPN(failAssert) ; If D = 0, then fail + D - 1 => E :JMPN(failAssert) ; If D = 0, then fail %ARRAY_MAX_LEN - D :JMPN(failAssert) ; If D > %ARRAY_MAX_LEN, then fail ; From here, 1 <= D <= %ARRAY_MAX_LEN @@ -213,22 +203,20 @@ array_div_long_mul_quo_inB: ; 3] Finally, we must ensure that the remainder is lower than inB $ => C :MLOAD(array_div_long_len_inB) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*%ARRAY_MAX_LEN - 1 :JMPN(outOfCountersStep) array_div_long_compare_inB2: - RR - 1 => RR - $ => A :MLOAD(array_div_inB + RR) + $ => A :MLOAD(array_div_long_inB + RR) A :MSTORE(array_compare_inA + RR) - RR :JMPZ(array_div_long_compare_rem, array_div_long_compare_inB2) + RR - 1 => RR :JMPN(array_div_long_compare_rem, array_div_long_compare_inB2) array_div_long_compare_rem: - E - 1 => E ${receiveRemainderChunk(E)} => A A :MSTORE(array_compare_inB + E) - E :JMPZ(array_div_long_compare2, array_div_long_compare_rem) + E - 1 => E :JMPN(array_div_long_compare2, array_div_long_compare_rem) array_div_long_compare2: :CALL(array_compare) @@ -241,23 +229,21 @@ array_div_long_compare2: ; prepare output and remainder to be added $ => C :MLOAD(array_mul_len_out) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 5*D - 1 :JMPN(outOfCountersStep) array_div_long_res_to_add: - RR - 1 => RR $ => A :MLOAD(array_mul_out + RR) A :MSTORE(array_add_AGTB_inA + RR) - RR :JMPZ(array_div_long_rem_to_add, array_div_long_res_to_add) + RR - 1 => RR :JMPN(array_div_long_rem_to_add, array_div_long_res_to_add) array_div_long_rem_to_add: - E - 1 => E ${receiveRemainderChunk(E)} => A A :MSTORE(array_div_long_rem + E) A :MSTORE(array_add_AGTB_inB + E) - E :JMPZ(array_div_long_add_res_rem, array_div_long_rem_to_add) + E - 1 => E :JMPN(array_div_long_add_res_rem, array_div_long_rem_to_add) array_div_long_add_res_rem: :CALL(array_add_AGTB) @@ -267,22 +253,20 @@ array_div_long_add_res_rem: ; prepare next $ => C :MLOAD(array_add_AGTB_len_out) $ => D :MLOAD(array_div_long_len_inA) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) array_div_long_compare_inA2: - RR - 1 => RR $ => A :MLOAD(array_add_AGTB_out + RR) A :MSTORE(array_compare_inA + RR) - RR :JMPZ(array_div_long_compare_inB3, array_div_long_compare_inA2) + RR - 1 => RR :JMPN(array_div_long_compare_inB3, array_div_long_compare_inA2) array_div_long_compare_inB3: - E - 1 => E $ => A :MLOAD(array_div_long_inA + E) A :MSTORE(array_compare_inB + E) - E :JMPZ(array_div_long_compare3, array_div_long_compare_inB3) + E - 1 => E :JMPN(array_div_long_compare3, array_div_long_compare_inB3) array_div_long_compare3: :CALL(array_compare) @@ -290,7 +274,7 @@ array_div_long_compare3: %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) 1 :MLOAD(array_compare_result) - 0 => B ; everything worked fine + 0 => B array_div_long_end: $ => RR :MLOAD(array_div_long_RR) diff --git a/main/modexp/array_lib/array_div_short.zkasm b/main/modexp/array_lib/array_div_short.zkasm index 27fe5e63..be44622f 100644 --- a/main/modexp/array_lib/array_div_short.zkasm +++ b/main/modexp/array_lib/array_div_short.zkasm @@ -52,32 +52,29 @@ array_div_short: %MAX_CNT_STEPS - STEP - 15 - 4*C - 3 :JMPN(outOfCountersStep) RR :MSTORE(array_div_short_RR) + C :MSTORE(array_div_short_len_inA) C :MSTORE(array_div_short_len_quo) ; Let's cover the edge cases - ; 1] Is inA == 0? - C => A 1 => B - $ :EQ, JMPNC(array_div_short_inA_continue) - 0 => B + ; 1] Is C == 1 and inA == 0? + C - B :JMPNZ(__array_div_short_inA_continue) $ => A :MLOAD(array_div_short_inA) - $ :EQ, JMPC(array_div_short_inA_is_zero) - array_div_short_inA_continue: + $ :LT, JMPC(array_div_short_inA_is_zero) + __array_div_short_inA_continue: ; 2] Is inB == 0? - 0 => B $ => A :MLOAD(array_div_short_inB) - $ :EQ, JMPC(array_div_short_inB_is_zero) + $ :LT, JMPC(array_div_short_inB_is_zero) ; Check whether inA = inB or inA < inB - C => RR + C - 1 => RR 1 => D array_div_short_inA_to_compare1: - RR - 1 => RR $ => A :MLOAD(array_div_short_inA + RR) A :MSTORE(array_compare_inA + RR) - RR :JMPZ(array_div_short_inB_to_compare, array_div_short_inA_to_compare1) + RR - 1 => RR :JMPN(array_div_short_inB_to_compare, array_div_short_inA_to_compare1) array_div_short_inB_to_compare: $ => A :MLOAD(array_div_short_inB) @@ -90,10 +87,8 @@ array_div_short_compare_inA_inB: %MAX_CNT_STEPS - STEP - 18 :JMPN(outOfCountersStep) $ => A :MLOAD(array_compare_result), JMPZ(array_div_short_inALTinB) - 1 => B - $ :EQ, JMPC(array_div_short_same_input) - - ; From here, it is known that inA > inB + A - 1 :JMPZ(array_div_short_same_input) + ; From here, inA > inB ; Strategy: Divide outside and check the result inside $${MPdiv_short(addr.array_div_short_inA,mem.array_div_short_len_inA,mem.array_div_short_inB)} @@ -104,7 +99,7 @@ array_div_short_compare_inA_inB: array_div_short_inA_is_zero: ; Is inB == 0? 0/0 is undefined $ => A :MLOAD(array_div_short_inB) - $ :EQ, JMPC(array_div_short_inB_is_zero) + $ :LT, JMPC(array_div_short_inB_is_zero) ; From here, inB != 0 ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1 @@ -149,16 +144,16 @@ array_div_short_prepare_mul_quo_inB: ; From here, the quotient is trimmed C :MSTORE(array_div_short_len_quo) - C => RR + + C - 1 => RR %MAX_CNT_STEPS - STEP - 5*%ARRAY_MAX_LEN - 4 :JMPN(outOfCountersStep) array_div_short_quo_to_mul: - RR - 1 => RR ${receiveQuotientChunk_short(RR)} => A A :MSTORE(array_div_short_quo + RR) A :MSTORE(array_mul_short_inA + RR) - RR :JMPZ(array_div_short_inB_to_mul, array_div_short_quo_to_mul) + RR - 1 => RR :JMPN(array_div_short_inB_to_mul, array_div_short_quo_to_mul) array_div_short_inB_to_mul: $ => A :MLOAD(array_div_short_inB) @@ -171,16 +166,15 @@ array_div_short_mul_quo_inB: ; prepare next $ => C :MLOAD(array_mul_short_len_out) - C => RR + C - 1 => RR %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) %MAX_CNT_STEPS - STEP - 4*C - 6 :JMPN(outOfCountersStep) array_div_short_result_to_add: - RR - 1 => RR $ => A :MLOAD(array_mul_short_out + RR) A :MSTORE(array_add_short_inA + RR) - RR :JMPZ(array_div_short_rem_to_add, array_div_short_result_to_add) + RR - 1 => RR :JMPN(array_div_short_rem_to_add, array_div_short_result_to_add) array_div_short_rem_to_add: ${receiveRemainderChunk_short()} => A @@ -200,22 +194,20 @@ array_div_short_add_result_rem: ; prepare next $ => C :MLOAD(array_add_short_len_out) $ => D :MLOAD(array_div_short_len_inA) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) array_div_short_result_to_compare: - RR - 1 => RR $ => A :MLOAD(array_add_short_out + RR) A :MSTORE(array_compare_inA + RR) - RR :JMPZ(array_div_short_inA_to_compare2, array_div_short_result_to_compare) + RR - 1 => RR :JMPN(array_div_short_inA_to_compare2, array_div_short_result_to_compare) array_div_short_inA_to_compare2: - E - 1 => E $ => A :MLOAD(array_div_short_inA + E) A :MSTORE(array_compare_inB + E) - E :JMPZ(array_div_short_compare_result_inA, array_div_short_inA_to_compare2) + E - 1 => E :JMPN(array_div_short_compare_result_inA, array_div_short_inA_to_compare2) array_div_short_compare_result_inA: :CALL(array_compare) @@ -223,7 +215,8 @@ array_div_short_compare_result_inA: %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) 1 :MLOAD(array_compare_result) - 0 => B + + 0 => B ; error code array_div_short_end: $ => RR :MLOAD(array_div_short_RR) diff --git a/main/modexp/array_lib/array_mul.zkasm b/main/modexp/array_lib/array_mul.zkasm index df12797a..c022e820 100644 --- a/main/modexp/array_lib/array_mul.zkasm +++ b/main/modexp/array_lib/array_mul.zkasm @@ -33,6 +33,7 @@ array_mul: %MAX_CNT_STEPS - STEP - 7 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_mul_RR) + C :MSTORE(array_mul_len_inA) D :MSTORE(array_mul_len_inB) diff --git a/main/modexp/array_lib/array_mul_long.zkasm b/main/modexp/array_lib/array_mul_long.zkasm index bb5f6c30..32fdd3f5 100644 --- a/main/modexp/array_lib/array_mul_long.zkasm +++ b/main/modexp/array_lib/array_mul_long.zkasm @@ -64,6 +64,7 @@ array_mul_long: %MAX_CNT_STEPS - STEP - 7 - 3*C - 3*D - 35*E - 2 - 4*C - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_mul_long_RR) + C :MSTORE(array_mul_long_len_inA) D :MSTORE(array_mul_long_len_inB) C + D :MSTORE(array_mul_long_len_out) diff --git a/main/modexp/array_lib/array_mul_short.zkasm b/main/modexp/array_lib/array_mul_short.zkasm index c06a7a8f..ffe26d61 100644 --- a/main/modexp/array_lib/array_mul_short.zkasm +++ b/main/modexp/array_lib/array_mul_short.zkasm @@ -48,6 +48,7 @@ array_mul_short: %MAX_CNT_STEPS - STEP - 6 - 3*C-3 - 18*C - 7 :JMPN(outOfCountersStep) RR :MSTORE(array_mul_short_RR) + C :MSTORE(array_mul_short_len_inA) C + 1 :MSTORE(array_mul_short_len_out) diff --git a/main/modexp/array_lib/array_square.zkasm b/main/modexp/array_lib/array_square.zkasm index 897d85e4..5c779185 100644 --- a/main/modexp/array_lib/array_square.zkasm +++ b/main/modexp/array_lib/array_square.zkasm @@ -64,6 +64,7 @@ array_square: %MAX_CNT_STEPS - STEP - 14 - 3*C - 83*E - 2 :JMPN(outOfCountersStep) RR :MSTORE(array_square_RR) + C :MSTORE(array_square_len_in) C + C :MSTORE(array_square_len_out) diff --git a/main/modexp/array_lib/unused/array_is_one.zkasm b/main/modexp/array_lib/unused/array_is_one.zkasm index 81f96e99..90f86d8d 100644 --- a/main/modexp/array_lib/unused/array_is_one.zkasm +++ b/main/modexp/array_lib/unused/array_is_one.zkasm @@ -18,10 +18,10 @@ array_is_one: ; Is C == 1 and in == 1? C => A 1 => B - $ :EQ, JMPNC(array_is_one_continue) + $ :EQ, JMPNC(__array_is_one_continue) $ => A :MLOAD(array_is_one_in) $ :EQ, JMPC(array_is_one_sure) - array_is_one_continue: + __array_is_one_continue: 0 :MSTORE(array_is_one_result) :JMP(array_is_one_end) diff --git a/main/modexp/array_lib/unused/array_is_zero.zkasm b/main/modexp/array_lib/unused/array_is_zero.zkasm index fca7224d..022f310f 100644 --- a/main/modexp/array_lib/unused/array_is_zero.zkasm +++ b/main/modexp/array_lib/unused/array_is_zero.zkasm @@ -18,11 +18,11 @@ array_is_zero: ; Is C == 1 and in == 0? C => A 1 => B - $ :EQ, JMPNC(array_is_zero_continue) + $ :EQ, JMPNC(__array_is_zero_continue) 0 => B $ => A :MLOAD(array_is_zero_in) $ :EQ, JMPC(array_is_zero_sure) - array_is_zero_continue: + __array_is_zero_continue: 0 :MSTORE(array_is_zero_result) :JMP(array_is_zero_end) diff --git a/main/modexp/modexp.zkasm b/main/modexp/modexp.zkasm index 77b50cc1..292980ca 100644 --- a/main/modexp/modexp.zkasm +++ b/main/modexp/modexp.zkasm @@ -194,21 +194,21 @@ modexp_pre_loop: ; Is E = 0? $ => A :MLOAD(modexp_Elen) 1 => B - $ :EQ, JMPNC(modexp_E_continue2) + $ :EQ, JMPNC(__modexp_E_continue_2) $ => A :MLOAD(modexp_E) - 0 => B + 0 => B ; error code $ :EQ, JMPC(modexp_end) - modexp_E_continue2: + __modexp_E_continue_2: modexp_loop: ; Is B = 0? $ => A :MLOAD(modexp_Blen) 1 => B - $ :EQ, JMPNC(modexp_B_continue3) + $ :EQ, JMPNC(__modexp_B_continue_3) $ => A :MLOAD(modexp_B) - 0 => B + 0 => B ; error code $ :EQ, JMPC(modexp_B_is_zero) - modexp_B_continue3: + __modexp_B_continue_3: ; Is E is odd? ; The base is 2^256, so I only need to check if the first chunk is odd to conclude that the whole number is odd. From 87426e4073e0d0ada74135cbaac6fede95dc6d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Masip?= Date: Tue, 19 Dec 2023 19:20:49 +0100 Subject: [PATCH 3/7] Two bugs fixed in array_mul_long/short --- main/modexp/array_lib/array_mul_long.zkasm | 80 ++++++++++----------- main/modexp/array_lib/array_mul_short.zkasm | 49 ++++++------- 2 files changed, 62 insertions(+), 67 deletions(-) diff --git a/main/modexp/array_lib/array_mul_long.zkasm b/main/modexp/array_lib/array_mul_long.zkasm index 32fdd3f5..3a625257 100644 --- a/main/modexp/array_lib/array_mul_long.zkasm +++ b/main/modexp/array_lib/array_mul_long.zkasm @@ -13,23 +13,19 @@ ;; · out = inA·inB, with len(out) <= C + D ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_mul_long(a: bigint[], b: bigint[], B: bigint): bigint[] { +; function array_mul_long(a: bigint[], b: bigint[], base: bigint): bigint[] { ; const alen = a.length; ; const blen = b.length; ; const len = alen + blen; ; const result = new Array(len).fill(0n); ; let product: bigint; ; let carry: bigint; -; let ai: bigint; -; let bj: bigint; ; for (let i = 0; i < alen; i++) { -; ai = a[i]; ; for (let j = 0; j < blen; j++) { -; bj = b[j]; -; product = ai * bj + result[i + j]; -; carry = product / B; -; result[i + j] = product - carry * B; -; result[i + j + 1] += carry; +; product = a[i] * b[j] + out[i+j]; +; carry = product / base; +; out[i+j] = product - carry * base; +; out[i + j + 1] += carry; ; } ; } ; trim(result); @@ -43,7 +39,7 @@ VAR GLOBAL array_mul_long_len_inA VAR GLOBAL array_mul_long_len_inB VAR GLOBAL array_mul_long_len_out -VAR GLOBAL array_mul_long_result_carry +VAR GLOBAL array_mul_long_out_chunk_2 VAR GLOBAL array_mul_long_RR @@ -69,36 +65,28 @@ array_mul_long: D :MSTORE(array_mul_long_len_inB) C + D :MSTORE(array_mul_long_len_out) - C + D => E ; auxiliar index + C + D - 1 => E ; auxiliar index 0 => RCX ; first index in loops 0 => RR ; second index in loops array_mul_long_clean_out: - E - 1 => E 0 :MSTORE(array_mul_long_out + E) - E :JMPZ(array_mul_long_loopZero2inB, array_mul_long_clean_out) + E - 1 => E :JMPN(array_mul_long_loopZero2inB, array_mul_long_clean_out) ; Begin of branching -array_mul_long_add_carry: - D + 1 => D :JMP(return_array_mul_long_add_carry) - -array_mul_long_add_result_carry: - 1 :MSTORE(array_mul_long_result_carry) - :JMP(return_array_mul_long_add_result_carry) - array_mul_long_loop_index_check: RCX + 1 => RCX - RCX => A $ => B :MLOAD(array_mul_long_len_inA) - $ :EQ, JMPC(array_mul_long_prep_trim_in) + B - RCX :JMPZ(array_mul_long_prep_trim_in) - 0 => RR - :JMP(return_array_mul_long_loop_index_check) + 0 => RR ; reset the second index ; End of branching array_mul_long_loopZero2inB: + ; The result will be stored as D·base + C + RCX => E - ; product = a_i * b_j + out[i + j] + ; 1] a[i]·b[j], where a[i],a[j] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks $ => A :MLOAD(array_mul_long_inA + E) $ => B :MLOAD(array_mul_long_inB + RR) 0 => C @@ -106,46 +94,52 @@ array_mul_long_loopZero2inB: ${_arrayLongMul_AB >> 256} => D ${_arrayLongMul_AB} => E :ARITH - ; sum lower part + ; 2] proudct = a[i]·b[j] + out[i+j], where out[i+j] ∈ [0,base-1]: This number cannot be GT (base - 1)·base, two chunks E => A RCX + RR => E $ => B :MLOAD(array_mul_long_out + E) - $ => C :ADD, JMPC(array_mul_long_add_carry) - return_array_mul_long_add_carry: - - ; sum higher part + $ => C :ADD, JMPNC(__array_mul_long_no_carry_continue_1) + ;----------------- + ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition D => A - $ => B :MLOAD(array_mul_long_result_carry) + 1 => B $ => D :ADD + ;----------------- + __array_mul_long_no_carry_continue_1: + $ => A :MLOAD(array_mul_long_out_chunk_2) + D => B + $ => D :ADD ; the number is of two chunks, no carry can be generated here - ; out[i + j] = product - carry·B + ; out[i+j] = product - carry·B C :MSTORE(array_mul_long_out + E) - ; out[i + j + 1] += carry + ; out[i+j+1] += carry, where carry ∈ [0,base-1]: This number cannot be GT base + (base-3), two chunks E + 1 => E $ => A :MLOAD(array_mul_long_out + E) D => B - $ => C :ADD, JMPC(array_mul_long_add_result_carry) - 0 :MSTORE(array_mul_long_result_carry) - return_array_mul_long_add_result_carry: + $ => C :ADD, JMPNC(__array_mul_long_no_carry_continue_2) + ;----------------- + 1 :MSTORE(array_mul_long_out_chunk_2) + :JMP(__array_mul_long_carry_continue) + __array_mul_long_no_carry_continue_2: + 0 :MSTORE(array_mul_long_out_chunk_2) + __array_mul_long_carry_continue: + ;----------------- + C :MSTORE(array_mul_long_out + E) RR + 1 => RR - RR => A $ => B :MLOAD(array_mul_long_len_inB) - $ :EQ, JMPC(array_mul_long_loop_index_check) - return_array_mul_long_loop_index_check: - :JMP(array_mul_long_loopZero2inB) + B - RR :JMPZ(array_mul_long_loop_index_check, array_mul_long_loopZero2inB) array_mul_long_prep_trim_in: $ => C :MLOAD(array_mul_long_len_out) - C => E + C - 1 => E array_mul_long_trim_in: - E - 1 => E $ => A :MLOAD(array_mul_long_out + E) A :MSTORE(array_trim_in + E) - E :JMPZ(array_mul_long_trim, array_mul_long_trim_in) + E - 1 => E :JMPN(array_mul_long_trim, array_mul_long_trim_in) array_mul_long_trim: :CALL(array_trim) diff --git a/main/modexp/array_lib/array_mul_short.zkasm b/main/modexp/array_lib/array_mul_short.zkasm index ffe26d61..892dae46 100644 --- a/main/modexp/array_lib/array_mul_short.zkasm +++ b/main/modexp/array_lib/array_mul_short.zkasm @@ -11,7 +11,7 @@ ;; · out = inA·inB, with len(out) <= C + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_mul_short(a: bigint[], b: bigint, B: bigint): bigint[] { +; function array_mul_short(a: bigint[], b: bigint, base: bigint): bigint[] { ; const alen = a.length; ; const len = alen; ; const result = new Array(len).fill(0n); @@ -20,8 +20,8 @@ ; let i; ; for (i = 0; i < alen; i++) { ; product = a[i] * b + carry; -; carry = product / B; -; result[i] = product - carry * B; +; carry = product / base; +; out[i] = product - carry * base; ; } ; if (carry > 0n) { @@ -52,23 +52,19 @@ array_mul_short: C :MSTORE(array_mul_short_len_inA) C + 1 :MSTORE(array_mul_short_len_out) - C + 1 => E ; auxiliar index + C => E ; auxiliar index 0 => RCX ; index in loops 0 :MSTORE(array_mul_short_carry) array_mul_short_clean_out: - E - 1 => E 0 :MSTORE(array_mul_short_out + E) - E :JMPZ(array_mul_short_loopZero2inA, array_mul_short_clean_out) - -; Begin of branching -array_mul_short_add_carry: - D + 1 => D :JMP(return_array_mul_short_add_carry) -; End of branching + E - 1 => E :JMPN(array_mul_short_loopZero2inA, array_mul_short_clean_out) array_mul_short_loopZero2inA: + ; The result will be stored as D·base + C + RCX => E - ; product = a_i * b + carry + ; 1] a[i] * b, where a[i],b ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks $ => A :MLOAD(array_mul_short_inA + E) $ => B :MLOAD(array_mul_short_inB) 0 => C @@ -76,41 +72,46 @@ array_mul_short_loopZero2inA: ${_arrayShortMul_AB >> 256} => D ${_arrayShortMul_AB} => E :ARITH + ; 2] product = a[i] * b + carry, where carry ∈ [0,base-1]: This number cannot be GT (base - 1)·base, two chunks E => A $ => B :MLOAD(array_mul_short_carry) - $ => C :ADD, JMPC(array_mul_short_add_carry) - return_array_mul_short_add_carry: + $ => C :ADD, JMPNC(__array_mul_short_no_carry_continue) + ;----------------- + ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition + D => A + 1 => B + $ => D :ADD + ;----------------- + __array_mul_short_no_carry_continue: + + ; carry = product / base D :MSTORE(array_mul_short_carry) - ; out[i] = product - carry·2²⁵⁶ + ; out[i] = product - carry·base RCX => E C :MSTORE(array_mul_short_out + E) RCX + 1 => RCX - RCX => A $ => B :MLOAD(array_mul_short_len_inA) - $ :EQ, JMPC(array_mul_short_carry_check, array_mul_short_loopZero2inA) + B - RCX :JMPZ(array_mul_short_carry_check, array_mul_short_loopZero2inA) -; If carry > 0, we need to add it to the output +; If the last carry > 0, we need to insert it to the output array_mul_short_carry_check: - $ => A :MLOAD(array_mul_short_carry) - 0 => B - $ :EQ, JMPC(array_mul_short_prep_trim_in) + $ => A :MLOAD(array_mul_short_carry), JMPZ(array_mul_short_prep_trim_in) RCX => E A :MSTORE(array_mul_short_out + E) array_mul_short_prep_trim_in: $ => C :MLOAD(array_mul_short_len_out) - C => E + C - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) array_mul_short_trim_in: - E - 1 => E $ => A :MLOAD(array_mul_short_out + E) A :MSTORE(array_trim_in + E) - E :JMPZ(array_mul_short_trim, array_mul_short_trim_in) + E - 1 => E :JMPZ(array_mul_short_trim, array_mul_short_trim_in) array_mul_short_trim: :CALL(array_trim) From b99c96b2f304ebd1d7004755453c0d121629449b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Masip?= Date: Tue, 19 Dec 2023 19:57:18 +0100 Subject: [PATCH 4/7] A first full refactor done --- main/modexp/array_lib/array_add_AGTB.zkasm | 10 +- main/modexp/array_lib/array_add_short.zkasm | 6 +- main/modexp/array_lib/array_div.zkasm | 6 +- main/modexp/array_lib/array_div_long.zkasm | 2 +- main/modexp/array_lib/array_div_short.zkasm | 2 +- main/modexp/array_lib/array_mul.zkasm | 32 +++--- main/modexp/array_lib/array_square.zkasm | 46 ++++---- .../array_lib/utils/array_compare.zkasm | 13 +-- main/modexp/array_lib/utils/array_trim.zkasm | 1 + main/modexp/modexp.zkasm | 103 ++++++++---------- 10 files changed, 94 insertions(+), 127 deletions(-) diff --git a/main/modexp/array_lib/array_add_AGTB.zkasm b/main/modexp/array_lib/array_add_AGTB.zkasm index 8e28339c..3e43b739 100644 --- a/main/modexp/array_lib/array_add_AGTB.zkasm +++ b/main/modexp/array_lib/array_add_AGTB.zkasm @@ -13,7 +13,7 @@ ;; · out = inA + inB, with len(out) <= C + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_add_AGTB(a: bigint[], b: bigint[], B: bigint): bigint[] { +; function array_add_AGTB(a: bigint[], b: bigint[], base: bigint): bigint[] { ; const alen = a.length; ; const blen = b.length; ; let result = new Array(alen); @@ -21,13 +21,13 @@ ; let carry = 0n; ; for (let i = 0; i < blen; i++) { ; sum = a[i] + b[i] + carry; -; carry = sum >= B ? 1n : 0n; -; result[i] = sum - carry * B; +; carry = sum >= base ? 1n : 0n; +; out[i] = sum - carry * base; ; } ; for (let i = blen; i < alen; i++) { ; sum = a[i] + carry; -; carry = sum == B ? 1n : 0n; // the past carry is at most 1n -; result[i] = sum - carry * B; +; carry = sum == base ? 1n : 0n; // the past carry is at most 1n +; out[i] = sum - carry * base; ; } ; if (carry === 1n) { diff --git a/main/modexp/array_lib/array_add_short.zkasm b/main/modexp/array_lib/array_add_short.zkasm index a4717ca5..b2afa1ef 100644 --- a/main/modexp/array_lib/array_add_short.zkasm +++ b/main/modexp/array_lib/array_add_short.zkasm @@ -10,15 +10,15 @@ ;; · out = inA + inB, with len(out) <= C + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_add_short(a: bigint[], b: bigint, B: bigint): bigint[] { +; function array_add_short(a: bigint[], b: bigint, base: bigint): bigint[] { ; const alen = a.length; ; let result = new Array(alen); ; let sum = 0n; ; let carry = b; ; for (let i = 0; i < alen; i++) { ; sum = a[i] + carry; -; carry = sum >= B ? 1n : 0n; -; result[i] = sum - carry * B; +; carry = sum >= base ? 1n : 0n; +; out[i] = sum - carry * base; ; } ; if (carry === 1n) { diff --git a/main/modexp/array_lib/array_div.zkasm b/main/modexp/array_lib/array_div.zkasm index 2e22d4ff..7e1f7787 100644 --- a/main/modexp/array_lib/array_div.zkasm +++ b/main/modexp/array_lib/array_div.zkasm @@ -13,7 +13,7 @@ ;; · [quo,rem] = [inA / inB, inA % inB], with len(quo) <= C - D + 1, len(rem) <= D ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_div(a: bigint[], b: bigint[], B: bigint): bigint[] { +; function array_div(a: bigint[], b: bigint[], base: bigint): bigint[] { ; if (a === [0n]) { ; if (b === [0n]) { ; throw new Error("Division by zero"); @@ -30,9 +30,9 @@ ; } ; ; if (b.length === 1) { -; return array_div_short(a, b, B); +; return array_div_short(a, b, base); ; } -; return array_div_long(a, b, B); +; return array_div_long(a, b, base); ; } VAR GLOBAL array_div_inA[%ARRAY_MAX_LEN] diff --git a/main/modexp/array_lib/array_div_long.zkasm b/main/modexp/array_lib/array_div_long.zkasm index e3352750..47776e7a 100644 --- a/main/modexp/array_lib/array_div_long.zkasm +++ b/main/modexp/array_lib/array_div_long.zkasm @@ -13,7 +13,7 @@ ;; · [quo,rem] = [inA / inB, inA % inB], with len(quo) <= C - D + 1, len(rem) <= D ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_div_long(a: bigint[], b: bigint[], B: bigint): bigint[] { +; function array_div_long(a: bigint[], b: bigint[], base: bigint): bigint[] { ; if (a === [0n]) { ; if (b === [0n]) { ; throw new Error("Division by zero"); diff --git a/main/modexp/array_lib/array_div_short.zkasm b/main/modexp/array_lib/array_div_short.zkasm index be44622f..7b07b403 100644 --- a/main/modexp/array_lib/array_div_short.zkasm +++ b/main/modexp/array_lib/array_div_short.zkasm @@ -12,7 +12,7 @@ ;; · [quo,rem] = [inA / inB[0], inA % inB[0]], with len(quo) <= C, len(rem) = 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_div_short(a: bigint[], b: bigint, B: bigint): bigint[] { +; function array_div_short(a: bigint[], b: bigint, base: bigint): bigint[] { ; if (a === [0n]) { ; if (b === 0n) { ; throw new Error("Division by zero"); diff --git a/main/modexp/array_lib/array_mul.zkasm b/main/modexp/array_lib/array_mul.zkasm index c022e820..98b73bbb 100644 --- a/main/modexp/array_lib/array_mul.zkasm +++ b/main/modexp/array_lib/array_mul.zkasm @@ -12,11 +12,11 @@ ;; · out = inA·inB, with len(out) <= C + D ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; function array_mul(a: bigint[], b: bigint[], B: bigint): bigint[] { +; function array_mul(a: bigint[], b: bigint[], base: bigint): bigint[] { ; if (b.length === 1) { -; return array_mul_short(a, b, B); +; return array_mul_short(a, b, base); ; } -; return array_mul_long(a, b, B); +; return array_mul_long(a, b, base); ; } VAR GLOBAL array_mul_inA[%ARRAY_MAX_LEN] @@ -37,22 +37,19 @@ array_mul: C :MSTORE(array_mul_len_inA) D :MSTORE(array_mul_len_inB) - C => RR - D => A,E - 1 => B - $ :EQ, JMPC(array_mul_inA_to_mul_short) ; worst case is mul long + C - 1 => RR + D - 1 => E + D - 1 :JMPZ(array_mul_inA_to_mul_short) ; worst case is mul long ; Long array_mul_inA_to_mul_long: - RR - 1 => RR $ => A :MLOAD(array_mul_inA + RR) A :MSTORE(array_mul_long_inA + RR) - RR :JMPZ(array_mul_inB_to_mul_long, array_mul_inA_to_mul_long) + RR - 1 => RR :JMPN(array_mul_inB_to_mul_long, array_mul_inA_to_mul_long) array_mul_inB_to_mul_long: - E - 1 => E $ => A :MLOAD(array_mul_inB + E) A :MSTORE(array_mul_long_inB + E) - E :JMPZ(array_mul_compute_long, array_mul_inB_to_mul_long) + E - 1 => E :JMPN(array_mul_compute_long, array_mul_inB_to_mul_long) array_mul_compute_long: :CALL(array_mul_long) @@ -61,22 +58,20 @@ array_mul_compute_long: $ => C :MLOAD(array_mul_long_len_out) C :MSTORE(array_mul_len_out) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 2 :JMPN(outOfCountersStep) array_mul_assign_long: - RR - 1 => RR $ => A :MLOAD(array_mul_long_out + RR) A :MSTORE(array_mul_out + RR) - RR :JMPZ(array_mul_end, array_mul_assign_long) + RR - 1 => RR :JMPN(array_mul_end, array_mul_assign_long) ; Short array_mul_inA_to_mul_short: - RR - 1 => RR $ => A :MLOAD(array_mul_inA + RR) A :MSTORE(array_mul_short_inA + RR) - RR :JMPZ(array_mul_inB_to_mul_short, array_mul_inA_to_mul_short) + RR - 1 => RR :JMPN(array_mul_inB_to_mul_short, array_mul_inA_to_mul_short) array_mul_inB_to_mul_short: $ => A :MLOAD(array_mul_inB) @@ -89,15 +84,14 @@ array_mul_compute_short: $ => C :MLOAD(array_mul_short_len_out) C :MSTORE(array_mul_len_out) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 2 :JMPN(outOfCountersStep) array_mul_assign_short: - RR - 1 => RR $ => A :MLOAD(array_mul_short_out + RR) A :MSTORE(array_mul_out + RR) - RR :JMPZ(array_mul_end, array_mul_assign_short) + RR - 1 => RR :JMPN(array_mul_end, array_mul_assign_short) array_mul_end: $ => RR :MLOAD(array_mul_RR) diff --git a/main/modexp/array_lib/array_square.zkasm b/main/modexp/array_lib/array_square.zkasm index 5c779185..a6eec480 100644 --- a/main/modexp/array_lib/array_square.zkasm +++ b/main/modexp/array_lib/array_square.zkasm @@ -15,17 +15,13 @@ ; let out = new Array(2*len).fill(0n); ; let product: bigint; ; let carry: bigint; -; let a_i: bigint; -; let a_j: bigint; ; for (let i = 0; i < len; i++) { -; a_i = a[i]; -; carry = 0n - a_i * a_i; +; carry = 0n - a[i] * a[i]; ; for (var j = i; j < len; j++) { -; a_j = a[j]; -; product = 2n * (a_i * a_j) + out[i + j] + carry; +; product = 2n * (a[i] * a[j]) + out[i+j] + carry; ; carry = product / base; -; out[i + j] = product - carry * base; +; out[i+j] = product - carry * base; ; } ; out[i + len] = carry; ; } @@ -68,12 +64,11 @@ array_square: C :MSTORE(array_square_len_in) C + C :MSTORE(array_square_len_out) - 0 => RCX ; first index in loops - C + C => RR ; second index in loops + 0 => RCX,RR ; first and second indexes in loops + C + C - 1 => E array_square_clean_out: - RR - 1 => RR - 0 :MSTORE(array_square_out + RR) - RR :JMPZ(array_square_ai_times_ai, array_square_clean_out) + 0 :MSTORE(array_square_out + E) + E - 1 => E :JMPN(array_square_ai_times_ai, array_square_clean_out) ; Begin of branching ; We perform subtraction of a value with three chunks @@ -112,8 +107,8 @@ array_square_loop_index_check: ; End of branching array_square_ai_times_ai: - ; carry = 0 - a_i·a_i - ; a_i·a_i, where a_i ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks + ; carry = 0 - a[i]·a[i] + ; a[i]·a[i], where a[i] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks $ => A,B :MLOAD(array_square_in + RR) 0 => C $${var _arraySquare_aiai = A*B} @@ -124,10 +119,10 @@ array_square_ai_times_ai: 0 :MSTORE(array_square_carry_sign) array_square_loopRR2len: - ; product = 2·(a_i·a_j) + out[i + j] + carry (in the worst case, this is a 3-chunk number) + ; product = 2·(a[i]·a[j]) + out[i+j] + carry (in the worst case, this is a 3-chunk number) ; The result will be stored as array_square_chunk_3·base² + D·base + C - ; 1] a_i·a_j, where a_i,a_j ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks + ; 1] a[i]·a[j], where a[i],a[j] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks RCX => E $ => A :MLOAD(array_square_in + E) $ => B :MLOAD(array_square_in + RR) @@ -137,7 +132,7 @@ array_square_loopRR2len: ${_arraySquare_aiaj} => E :ARITH D :MSTORE(array_square_aiaj_chunk_2) - ; 2] 2·a_i·a_j: This number cannot be GT base² + (base - 4)·base + 2, three chunks + ; 2] 2·a[i]·a[j]: This number cannot be GT base² + (base - 4)·base + 2, three chunks E => A,B $ => C :ADD, JMPNC(__array_square_no_carry_continue_1) ;----------------- @@ -155,8 +150,8 @@ array_square_loopRR2len: ;----------------- __array_square_no_carry_continue_2: - ; 3] 2·a_i·a_j + out[i + j]: - ; a) j < len-1: This number cannot be GT base² + (base - 3)·base + 1, as out[i + j] < base + ; 3] 2·a[i]·a[j] + out[i+j]: + ; a) j < len-1: This number cannot be GT base² + (base - 3)·base + 1, as out[i+j] < base ; b) j == len-1: This number cannot be GT base² + (base - 3)·base + base - 1, as out[i + len] <= base + (base - 3) ; In both cases, three chunks RCX + RR => E @@ -185,7 +180,7 @@ array_square_loopRR2len: ;----------------- __array_square_no_carry_continue_4: - ; 4] product = 2·a_i·a_j + out[i + j] + carry: This number cannot be GT base² + (base - 2)·base, three chunks + ; 4] product = 2·a[i]·a[j] + out[i+j] + carry: This number cannot be GT base² + (base - 2)·base, three chunks C => A $ => B :MLOAD(array_square_carry_chunk_1) $ :MLOAD(array_square_carry_sign), JMPZ(array_square_is_negative_1) @@ -216,26 +211,25 @@ array_square_loopRR2len: A :MSTORE(array_square_carry_chunk_2) 1 :MSTORE(array_square_carry_sign) - ; out[i + j] = product - carry·base; + ; out[i+j] = product - carry·base; RCX + RR => E C :MSTORE(array_square_out + E) 0 :MSTORE(array_square_chunk_3) ; reset the third chunk - RR + 1 => RR,A + RR + 1 => RR $ => B :MLOAD(array_square_len_in) - B - A :JMPZ(array_square_loop_index_check, array_square_loopRR2len) ; This subtraction is safe + B - RR :JMPZ(array_square_loop_index_check, array_square_loopRR2len) ; This subtraction is safe array_square_prep_trim_in: $ => C :MLOAD(array_square_len_out) - C => E %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) + C - 1 => E array_square_trim_in: - E - 1 => E $ => A :MLOAD(array_square_out + E) A :MSTORE(array_trim_in + E) - E :JMPZ(array_square_trim, array_square_trim_in) + E - 1 => E :JMPN(array_square_trim, array_square_trim_in) array_square_trim: :CALL(array_trim) diff --git a/main/modexp/array_lib/utils/array_compare.zkasm b/main/modexp/array_lib/utils/array_compare.zkasm index 292626d0..3a803d12 100644 --- a/main/modexp/array_lib/utils/array_compare.zkasm +++ b/main/modexp/array_lib/utils/array_compare.zkasm @@ -51,16 +51,11 @@ array_compare: RR :MSTORE(array_compare_RR) ; Start by comparing the lengths of the arrays - C => A - D => B - $ :LT, JMPC(array_compare_ALTB) - C => B - D => A - $ :LT, JMPC(array_compare_AGTB) + C - D :JMPN(array_compare_ALTB) + D - C :JMPN(array_compare_AGTB) - C => E + C - 1 => E array_compare_same_len: - E - 1 => E $ => A :MLOAD(array_compare_inA + E) $ => B :MLOAD(array_compare_inB + E) $ :LT, JMPC(array_compare_ALTB) @@ -69,7 +64,7 @@ array_compare_same_len: $ => B :MLOAD(array_compare_inA + E) $ :LT, JMPC(array_compare_AGTB) - E :JMPZ(array_compare_AEQB, array_compare_same_len) + E - 1 => E :JMPN(array_compare_AEQB, array_compare_same_len) array_compare_AGTB: 2 :MSTORE(array_compare_result) diff --git a/main/modexp/array_lib/utils/array_trim.zkasm b/main/modexp/array_lib/utils/array_trim.zkasm index e0d5341f..a52fd645 100644 --- a/main/modexp/array_lib/utils/array_trim.zkasm +++ b/main/modexp/array_lib/utils/array_trim.zkasm @@ -35,6 +35,7 @@ array_trim_loop: %MAX_CNT_STEPS - STEP - 6 :JMPN(outOfCountersStep) E - 1 => E :JMPZ(array_trim_end) + $ => A :MLOAD(array_trim_in + E) 0 => B $ :EQ, JMPZ(array_trim_end, array_trim_loop) diff --git a/main/modexp/modexp.zkasm b/main/modexp/modexp.zkasm index 292980ca..4310c3f7 100644 --- a/main/modexp/modexp.zkasm +++ b/main/modexp/modexp.zkasm @@ -17,21 +17,21 @@ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; function modexp(b: bigint[], exp: bigint[], mod: bigint[], B: bigint): bigint[] { +;; function modexp(b: bigint[], exp: bigint[], mod: bigint[], base: bigint): bigint[] { ;; if (array_is_zero(mod) || array_is_one(mod)) return [0n]; ;; if (array_is_zero(b)) return [0n]; ;; if (array_is_one(b)) return [1n]; ;; if (array_is_zero(e)) return [1n]; ;; ;; let r = [1n]; -;; let base = array_div(b, mod, B)[1]; +;; let base = array_div(b, mod, base)[1]; ;; while (!array_is_zero(exp)) { ;; if (array_is_zero(base)) return [0n]; ;; if (isOdd(exp)) { -;; r = array_div(array_mul(r, base, B),mod,B)[1]; +;; r = array_div(array_mul(r, base, base),mod,base)[1]; ;; } -;; exp = array_div_short(exp, 2n, B)[0]; -;; base = array_div(array_square(base, B),mod,B)[1]; +;; exp = array_div_short(exp, 2n, base)[0]; +;; base = array_div(array_square(base, base),mod,base)[1]; ;; } ;; return r; ;; }; @@ -75,24 +75,22 @@ modexp: ; prepare for computing B % M $ => C :MLOAD(modexp_Blen) $ => D :MLOAD(modexp_Mlen) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) ; Compute B = B % M ; ------------------- modexp_B_to_div: - RR - 1 => RR $ => A :MLOAD(modexp_B + RR) A :MSTORE(array_div_inA + RR) - RR :JMPZ(modexp_M_to_div1, modexp_B_to_div) + RR - 1 => RR :JMPN(modexp_M_to_div1, modexp_B_to_div) modexp_M_to_div1: - E - 1 => E $ => A :MLOAD(modexp_M + E) A :MSTORE(array_div_inB + E) - E :JMPZ(modexp_div_B_and_M, modexp_M_to_div1) + E - 1 => E :JMPN(modexp_div_B_and_M, modexp_M_to_div1) modexp_div_B_and_M: :CALL(array_div) @@ -101,15 +99,14 @@ modexp_div_B_and_M: $ => C :MLOAD(array_div_len_rem) C :MSTORE(modexp_Blen) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C :JMPN(outOfCountersStep) modexp_rem_from_div1: - RR - 1 => RR $ => A :MLOAD(array_div_rem + RR) A :MSTORE(modexp_B + RR) - RR :JMPZ(modexp_pre_loop, modexp_rem_from_div1) + RR - 1 => RR :JMPN(modexp_pre_loop, modexp_rem_from_div1) ; ------------------- ; Begin of edge cases @@ -123,24 +120,22 @@ modexp_B_is_zero: modexp_loop_multiply: $ => C :MLOAD(modexp_outlen) $ => D :MLOAD(modexp_Blen) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) ; Compute out * B ; ------------------- modexp_out_to_mul_long: - RR - 1 => RR $ => A :MLOAD(modexp_out + RR) A :MSTORE(array_mul_inA + RR) - RR :JMPZ(modexp_B_to_mul_long, modexp_out_to_mul_long) + RR - 1 => RR :JMPN(modexp_B_to_mul_long, modexp_out_to_mul_long) modexp_B_to_mul_long: - E - 1 => E $ => A :MLOAD(modexp_B + E) A :MSTORE(array_mul_inB + E) - E :JMPZ(modexp_mul_long_out_and_B, modexp_B_to_mul_long) + E - 1 => E :JMPN(modexp_mul_long_out_and_B, modexp_B_to_mul_long) modexp_mul_long_out_and_B: :CALL(array_mul) @@ -149,23 +144,21 @@ modexp_mul_long_out_and_B: $ => C :MLOAD(array_mul_len_out) $ => D :MLOAD(modexp_Mlen) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) ; Compute out = (out * B) % M modexp_out_to_div1: - RR - 1 => RR $ => A :MLOAD(array_mul_out + RR) A :MSTORE(array_div_inA + RR) - RR :JMPZ(modexp_M_to_div, modexp_out_to_div1) + RR - 1 => RR :JMPN(modexp_M_to_div, modexp_out_to_div1) modexp_M_to_div: - E - 1 => E $ => A :MLOAD(modexp_M + E) A :MSTORE(array_div_inB + E) - E :JMPZ(modexp_div_out_and_M2, modexp_M_to_div) + E - 1 => E :JMPN(modexp_div_out_and_M2, modexp_M_to_div) modexp_div_out_and_M2: :CALL(array_div) @@ -174,15 +167,14 @@ modexp_div_out_and_M2: $ => C :MLOAD(array_div_len_rem) C :MSTORE(modexp_outlen) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) modexp_rem_from_div2: - RR - 1 => RR $ => A :MLOAD(array_div_rem + RR) A :MSTORE(modexp_out + RR) - RR :JMPZ(return_modexp_loop_multiply, modexp_rem_from_div2) + RR - 1 => RR :JMPN(return_modexp_loop_multiply, modexp_rem_from_div2) ; ------------------- ; End of branching @@ -191,24 +183,21 @@ modexp_pre_loop: %MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary) %MAX_CNT_STEPS - STEP - 21 :JMPN(outOfCountersStep) - ; Is E = 0? - $ => A :MLOAD(modexp_Elen) + ; Is Elen = 1 and E = 0? 1 => B - $ :EQ, JMPNC(__modexp_E_continue_2) + $ => A :MLOAD(modexp_Elen) + A - B :JMPNZ(__modexp_E_continue) $ => A :MLOAD(modexp_E) - 0 => B ; error code - $ :EQ, JMPC(modexp_end) - __modexp_E_continue_2: + $ :LT, JMPC(modexp_end) ; we are done + __modexp_E_continue: modexp_loop: - ; Is B = 0? + ; Is Blen = 1 and B = 0? $ => A :MLOAD(modexp_Blen) - 1 => B - $ :EQ, JMPNC(__modexp_B_continue_3) + A - B :JMPNZ(__modexp_B_continue) $ => A :MLOAD(modexp_B) - 0 => B ; error code - $ :EQ, JMPC(modexp_B_is_zero) - __modexp_B_continue_3: + $ :LT, JMPC(modexp_B_is_zero) + __modexp_B_continue: ; Is E is odd? ; The base is 2^256, so I only need to check if the first chunk is odd to conclude that the whole number is odd. @@ -220,50 +209,47 @@ modexp_loop: %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) $ => C :MLOAD(modexp_Elen) - 2 :MSTORE(array_div_short_inB) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) ; Compute E = E // 2 ; ------------------- modexp_E_to_div_short: - RR - 1 => RR $ => A :MLOAD(modexp_E + RR) A :MSTORE(array_div_short_inA + RR) - RR :JMPZ(modexp_div_E_and_2, modexp_E_to_div_short) + RR - 1 => RR :JMPN(modexp_div_E_and_2, modexp_E_to_div_short) modexp_div_E_and_2: + 2 :MSTORE(array_div_short_inB) :CALL(array_div_short) %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) $ => C :MLOAD(array_div_short_len_quo) C :MSTORE(modexp_Elen) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 2 :JMPN(outOfCountersStep) modexp_quo_from_div_short: - RR - 1 => RR $ => A :MLOAD(array_div_short_quo + RR) A :MSTORE(modexp_E + RR) - RR :JMPZ(modexp_pre_B_square, modexp_quo_from_div_short) + RR - 1 => RR :JMPN(modexp_pre_B_square, modexp_quo_from_div_short) ; ------------------- ; Compute B^2 ; ------------------- modexp_pre_B_square: $ => C :MLOAD(modexp_Blen) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) modexp_B_to_square1: - RR - 1 => RR $ => A :MLOAD(modexp_B + RR) A :MSTORE(array_square_in + RR) - RR :JMPZ(modexp_square_B, modexp_B_to_square1) + RR - 1 => RR :JMPN(modexp_square_B, modexp_B_to_square1) modexp_square_B: :CALL(array_square) @@ -272,23 +258,21 @@ modexp_square_B: $ => C :MLOAD(array_square_len_out) $ => D :MLOAD(modexp_Mlen) - C => RR - D => E + C - 1 => RR + D - 1 => E %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) ; Compute B = (B^2) % M modexp_out_to_div2: - RR - 1 => RR $ => A :MLOAD(array_square_out + RR) A :MSTORE(array_div_inA + RR) - RR :JMPZ(modexp_M_to_div2, modexp_out_to_div2) + RR - 1 => RR :JMPN(modexp_M_to_div2, modexp_out_to_div2) modexp_M_to_div2: - E - 1 => E $ => A :MLOAD(modexp_M + E) A :MSTORE(array_div_inB + E) - E :JMPZ(modexp_div_out_and_M1, modexp_M_to_div2) + E - 1 => E :JMPN(modexp_div_out_and_M1, modexp_M_to_div2) modexp_div_out_and_M1: :CALL(array_div) @@ -297,15 +281,14 @@ modexp_div_out_and_M1: $ => C :MLOAD(array_div_len_rem) C :MSTORE(modexp_Blen) - C => RR + C - 1 => RR %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) modexp_rem_from_div3: - RR - 1 => RR $ => A :MLOAD(array_div_rem + RR) A :MSTORE(modexp_B + RR) - RR :JMPZ(modexp_pre_loop, modexp_rem_from_div3) + RR - 1 => RR :JMPN(modexp_pre_loop, modexp_rem_from_div3) ; ------------------- modexp_end: From 0d41b5b4325c35f3c819420cf6510d6e3ed4fdf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Masip?= Date: Wed, 20 Dec 2023 10:01:55 +0100 Subject: [PATCH 5/7] Utils refactor done --- main/modexp/array_lib/utils/array_compare.zkasm | 5 ++--- main/modexp/array_lib/utils/array_trim.zkasm | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/main/modexp/array_lib/utils/array_compare.zkasm b/main/modexp/array_lib/utils/array_compare.zkasm index 3a803d12..39388f56 100644 --- a/main/modexp/array_lib/utils/array_compare.zkasm +++ b/main/modexp/array_lib/utils/array_compare.zkasm @@ -45,8 +45,8 @@ VAR GLOBAL array_compare_result VAR GLOBAL array_compare_RR array_compare: - %MAX_CNT_BINARY - CNT_BINARY - 2 - 2*C :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 8 - 8*C - 4 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2*C :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 4 - 7*C - 4 :JMPN(outOfCountersStep) RR :MSTORE(array_compare_RR) @@ -76,7 +76,6 @@ array_compare_AEQB: array_compare_ALTB: 0 :MSTORE(array_compare_result) - :JMP(array_compare_end) array_compare_end: $ => RR :MLOAD(array_compare_RR) diff --git a/main/modexp/array_lib/utils/array_trim.zkasm b/main/modexp/array_lib/utils/array_trim.zkasm index a52fd645..efb9b750 100644 --- a/main/modexp/array_lib/utils/array_trim.zkasm +++ b/main/modexp/array_lib/utils/array_trim.zkasm @@ -23,21 +23,22 @@ VAR GLOBAL array_trim_in[%ARRAY_MAX_LEN_DOUBLED] VAR GLOBAL array_trim_RR array_trim: - %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) RR :MSTORE(array_trim_RR) + 0 => B ; used for comparison in the whole loop + C => E ; scan from the last chunk to the first chunks until we find a non-zero chunk ; in case of zero input array, we return 1 array_trim_loop: %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 6 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) E - 1 => E :JMPZ(array_trim_end) $ => A :MLOAD(array_trim_in + E) - 0 => B $ :EQ, JMPZ(array_trim_end, array_trim_loop) array_trim_end: From c51fd319baa754d741ded28e18035c502629eadb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Masip?= Date: Wed, 20 Dec 2023 11:18:48 +0100 Subject: [PATCH 6/7] Counters corrected --- main/modexp/array_lib/array_add_AGTB.zkasm | 4 +-- main/modexp/array_lib/array_add_short.zkasm | 6 ++-- main/modexp/array_lib/array_div.zkasm | 13 ++++---- main/modexp/array_lib/array_div_long.zkasm | 20 ++++++------ main/modexp/array_lib/array_div_short.zkasm | 15 ++++----- main/modexp/array_lib/array_mul.zkasm | 11 +++---- main/modexp/array_lib/array_mul_long.zkasm | 6 ++-- main/modexp/array_lib/array_mul_short.zkasm | 8 ++--- main/modexp/array_lib/array_square.zkasm | 10 +++--- main/modexp/modexp.zkasm | 36 ++++++++++----------- 10 files changed, 63 insertions(+), 66 deletions(-) diff --git a/main/modexp/array_lib/array_add_AGTB.zkasm b/main/modexp/array_lib/array_add_AGTB.zkasm index 3e43b739..7bcbccf8 100644 --- a/main/modexp/array_lib/array_add_AGTB.zkasm +++ b/main/modexp/array_lib/array_add_AGTB.zkasm @@ -50,8 +50,8 @@ VAR GLOBAL array_add_AGTB_carry VAR GLOBAL array_add_AGTB_RR array_add_AGTB: - %MAX_CNT_BINARY - CNT_BINARY - 3*D - 1 - C+ D - 1 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 6 - 17*D - 4 - 11*C+11*D - 8 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2*D - C+ D :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 5 - 14*D - 3 - 9*C+9*D - 8 :JMPN(outOfCountersStep) RR :MSTORE(array_add_AGTB_RR) diff --git a/main/modexp/array_lib/array_add_short.zkasm b/main/modexp/array_lib/array_add_short.zkasm index b2afa1ef..6fe10b0b 100644 --- a/main/modexp/array_lib/array_add_short.zkasm +++ b/main/modexp/array_lib/array_add_short.zkasm @@ -38,8 +38,8 @@ VAR GLOBAL array_add_short_carry VAR GLOBAL array_add_short_RR array_add_short: - %MAX_CNT_BINARY - CNT_BINARY - 2*C - 1 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 6 - 12*C - 8 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - C :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 5 - 10*C - 8 :JMPN(outOfCountersStep) RR :MSTORE(array_add_short_RR) @@ -78,7 +78,7 @@ array_add_short_check_carry: E + 1 :MSTORE(array_add_short_len_out) :JMP(array_add_short_end) __array_add_short_continue_2: - E :MSTORE(array_add_short_len_out) + E :MSTORE(array_add_short_len_out) array_add_short_end: $ => RR :MLOAD(array_add_short_RR) diff --git a/main/modexp/array_lib/array_div.zkasm b/main/modexp/array_lib/array_div.zkasm index 7e1f7787..9a1e4e5e 100644 --- a/main/modexp/array_lib/array_div.zkasm +++ b/main/modexp/array_lib/array_div.zkasm @@ -52,8 +52,8 @@ VAR GLOBAL array_div_RR ; 1 - inB is zero array_div: - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 19 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 12 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_div_RR) @@ -90,8 +90,7 @@ array_div_compare_inB: array_div_compare: :CALL(array_compare) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 7 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 5 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) $ => A :MLOAD(array_compare_result), JMPZ(array_div_prep_inALTinB) A - 1 :JMPZ(array_div_same_input) @@ -159,7 +158,7 @@ array_div_inB_to_div_long: array_div_compute_long: :CALL(array_div_long) - %MAX_CNT_STEPS - STEP - 6 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 7 :JMPN(outOfCountersStep) $ => C :MLOAD(array_div_long_len_quo) $ => D :MLOAD(array_div_long_len_rem) @@ -168,7 +167,7 @@ array_div_compute_long: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*D - 2 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 2 :JMPN(outOfCountersStep) array_div_assign_long_quo: $ => A :MLOAD(array_div_long_quo + RR) @@ -200,7 +199,7 @@ array_div_compute_short: 1 :MSTORE(array_div_len_rem) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 4 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 4 :JMPN(outOfCountersStep) array_div_assign_short_quo: $ => A :MLOAD(array_div_short_quo + RR) diff --git a/main/modexp/array_lib/array_div_long.zkasm b/main/modexp/array_lib/array_div_long.zkasm index 47776e7a..51201964 100644 --- a/main/modexp/array_lib/array_div_long.zkasm +++ b/main/modexp/array_lib/array_div_long.zkasm @@ -50,8 +50,8 @@ VAR GLOBAL array_div_long_RR ; 1 - inB is zero array_div_long: - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 19 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 12 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_div_long_RR) @@ -88,8 +88,8 @@ array_div_long_compare_inB1: array_div_long_compare1: :CALL(array_compare) - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 15 :JMPN(outOfCountersStep) $ => A :MLOAD(array_compare_result), JMPZ(array_div_long_prep_inALTinB) A - 1 :JMPZ(array_div_long_same_input) @@ -167,7 +167,7 @@ array_div_long_prepare_mul_quo_inB: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 5*%ARRAY_MAX_LEN - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep) array_div_long_quo_to_mul: ${receiveQuotientChunk(RR)} => A @@ -183,8 +183,8 @@ array_div_long_inB_to_mul: array_div_long_mul_quo_inB: :CALL(array_mul) - %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 14 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) ; Check the remainder $0{receiveLenRemainder()} => D @@ -206,7 +206,7 @@ array_div_long_mul_quo_inB: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*%ARRAY_MAX_LEN - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*%ARRAY_MAX_LEN - 1 :JMPN(outOfCountersStep) array_div_long_compare_inB2: $ => A :MLOAD(array_div_long_inB + RR) @@ -232,7 +232,7 @@ array_div_long_compare2: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 5*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 4*D - 1 :JMPN(outOfCountersStep) array_div_long_res_to_add: $ => A :MLOAD(array_mul_out + RR) @@ -256,7 +256,7 @@ array_div_long_add_res_rem: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) array_div_long_compare_inA2: $ => A :MLOAD(array_add_AGTB_out + RR) diff --git a/main/modexp/array_lib/array_div_short.zkasm b/main/modexp/array_lib/array_div_short.zkasm index 7b07b403..22b2ddf7 100644 --- a/main/modexp/array_lib/array_div_short.zkasm +++ b/main/modexp/array_lib/array_div_short.zkasm @@ -47,9 +47,8 @@ VAR GLOBAL array_div_short_RR ; 1 - inB is zero array_div_short: - - %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 15 - 4*C - 3 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 11 - 3*C - 3 :JMPN(outOfCountersStep) RR :MSTORE(array_div_short_RR) @@ -83,8 +82,8 @@ array_div_short_inB_to_compare: array_div_short_compare_inA_inB: :CALL(array_compare) - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 18 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 13 :JMPN(outOfCountersStep) $ => A :MLOAD(array_compare_result), JMPZ(array_div_short_inALTinB) A - 1 :JMPZ(array_div_short_same_input) @@ -147,7 +146,7 @@ array_div_short_prepare_mul_quo_inB: C - 1 => RR - %MAX_CNT_STEPS - STEP - 5*%ARRAY_MAX_LEN - 4 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4*%ARRAY_MAX_LEN - 3 :JMPN(outOfCountersStep) array_div_short_quo_to_mul: ${receiveQuotientChunk_short(RR)} => A @@ -169,7 +168,7 @@ array_div_short_mul_quo_inB: C - 1 => RR %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 4*C - 6 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 6 :JMPN(outOfCountersStep) array_div_short_result_to_add: $ => A :MLOAD(array_mul_short_out + RR) @@ -197,7 +196,7 @@ array_div_short_add_result_rem: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) array_div_short_result_to_compare: $ => A :MLOAD(array_add_short_out + RR) diff --git a/main/modexp/array_lib/array_mul.zkasm b/main/modexp/array_lib/array_mul.zkasm index 98b73bbb..e4551c1b 100644 --- a/main/modexp/array_lib/array_mul.zkasm +++ b/main/modexp/array_lib/array_mul.zkasm @@ -29,8 +29,7 @@ VAR GLOBAL array_mul_len_out VAR GLOBAL array_mul_RR array_mul: - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 7 - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 6 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_mul_RR) @@ -54,13 +53,13 @@ array_mul_inB_to_mul_long: array_mul_compute_long: :CALL(array_mul_long) - %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) $ => C :MLOAD(array_mul_long_len_out) C :MSTORE(array_mul_len_out) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 2 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) array_mul_assign_long: $ => A :MLOAD(array_mul_long_out + RR) @@ -80,13 +79,13 @@ array_mul_inB_to_mul_short: array_mul_compute_short: :CALL(array_mul_short) - %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) $ => C :MLOAD(array_mul_short_len_out) C :MSTORE(array_mul_len_out) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 2 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) array_mul_assign_short: $ => A :MLOAD(array_mul_short_out + RR) diff --git a/main/modexp/array_lib/array_mul_long.zkasm b/main/modexp/array_lib/array_mul_long.zkasm index 3a625257..3f63c3a9 100644 --- a/main/modexp/array_lib/array_mul_long.zkasm +++ b/main/modexp/array_lib/array_mul_long.zkasm @@ -45,7 +45,7 @@ VAR GLOBAL array_mul_long_RR array_mul_long: %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith) - %MAX_CNT_STEPS - STEP - 6 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 9 :JMPN(outOfCountersStep) C => A D => B @@ -55,9 +55,9 @@ array_mul_long: B => D ; E holds C*D - %MAX_CNT_BINARY - CNT_BINARY - 5*E :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 4*E :JMPN(outOfCountersBinary) %MAX_CNT_ARITH - CNT_ARITH - E :JMPN(outOfCountersArith) - %MAX_CNT_STEPS - STEP - 7 - 3*C - 3*D - 35*E - 2 - 4*C - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 7 - 2*C - 2*D - 33*E - 2 - 3*C - 1 :JMPN(outOfCountersStep) RR :MSTORE(array_mul_long_RR) diff --git a/main/modexp/array_lib/array_mul_short.zkasm b/main/modexp/array_lib/array_mul_short.zkasm index 892dae46..506b9b6f 100644 --- a/main/modexp/array_lib/array_mul_short.zkasm +++ b/main/modexp/array_lib/array_mul_short.zkasm @@ -43,16 +43,16 @@ VAR GLOBAL array_mul_short_carry VAR GLOBAL array_mul_short_RR array_mul_short: - %MAX_CNT_BINARY - CNT_BINARY - 2*C - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 2*C :JMPN(outOfCountersBinary) %MAX_CNT_ARITH - CNT_ARITH - C :JMPN(outOfCountersArith) - %MAX_CNT_STEPS - STEP - 6 - 3*C-3 - 18*C - 7 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 6 - 2*C-2 - 18*C - 6 :JMPN(outOfCountersStep) RR :MSTORE(array_mul_short_RR) C :MSTORE(array_mul_short_len_inA) C + 1 :MSTORE(array_mul_short_len_out) - C => E ; auxiliar index + C => E ; auxiliar index 0 => RCX ; index in loops 0 :MSTORE(array_mul_short_carry) @@ -106,7 +106,7 @@ array_mul_short_prep_trim_in: $ => C :MLOAD(array_mul_short_len_out) C - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 1 :JMPN(outOfCountersStep) array_mul_short_trim_in: $ => A :MLOAD(array_mul_short_out + E) diff --git a/main/modexp/array_lib/array_square.zkasm b/main/modexp/array_lib/array_square.zkasm index a6eec480..25e9a9a8 100644 --- a/main/modexp/array_lib/array_square.zkasm +++ b/main/modexp/array_lib/array_square.zkasm @@ -47,7 +47,7 @@ VAR GLOBAL array_square_RR array_square: %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith) - %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 7 :JMPN(outOfCountersStep) C => A,B 0 => C,D @@ -55,9 +55,9 @@ array_square: A => C ; E holds C*C - %MAX_CNT_BINARY - CNT_BINARY - 10*E :JMPN(outOfCountersBinary) - %MAX_CNT_ARITH - CNT_ARITH - 1 - 2*E :JMPN(outOfCountersArith) - %MAX_CNT_STEPS - STEP - 14 - 3*C - 83*E - 2 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 9*E :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 1 - 2*E :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 5 - 2*C - 68*E - 2 :JMPN(outOfCountersStep) RR :MSTORE(array_square_RR) @@ -223,7 +223,7 @@ array_square_loopRR2len: array_square_prep_trim_in: $ => C :MLOAD(array_square_len_out) - %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 1 - 3*C - 1 :JMPN(outOfCountersStep) C - 1 => E array_square_trim_in: diff --git a/main/modexp/modexp.zkasm b/main/modexp/modexp.zkasm index 4310c3f7..6491c42a 100644 --- a/main/modexp/modexp.zkasm +++ b/main/modexp/modexp.zkasm @@ -78,7 +78,7 @@ modexp: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) ; Compute B = B % M ; ------------------- @@ -95,13 +95,13 @@ modexp_M_to_div1: modexp_div_B_and_M: :CALL(array_div) - %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) $ => C :MLOAD(array_div_len_rem) C :MSTORE(modexp_Blen) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C :JMPN(outOfCountersStep) modexp_rem_from_div1: $ => A :MLOAD(array_div_rem + RR) @@ -123,7 +123,7 @@ modexp_loop_multiply: C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) ; Compute out * B ; ------------------- @@ -140,14 +140,14 @@ modexp_B_to_mul_long: modexp_mul_long_out_and_B: :CALL(array_mul) - %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) $ => C :MLOAD(array_mul_len_out) $ => D :MLOAD(modexp_Mlen) C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) ; Compute out = (out * B) % M modexp_out_to_div1: @@ -163,13 +163,13 @@ modexp_M_to_div: modexp_div_out_and_M2: :CALL(array_div) - %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) $ => C :MLOAD(array_div_len_rem) C :MSTORE(modexp_outlen) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 1 :JMPN(outOfCountersStep) modexp_rem_from_div2: $ => A :MLOAD(array_div_rem + RR) @@ -180,8 +180,8 @@ modexp_rem_from_div2: modexp_pre_loop: ; In the worst case, the exponent is odd in each iteration - %MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 21 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 13 :JMPN(outOfCountersStep) ; Is Elen = 1 and E = 0? 1 => B @@ -211,7 +211,7 @@ modexp_loop: $ => C :MLOAD(modexp_Elen) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) ; Compute E = E // 2 ; ------------------- @@ -224,13 +224,13 @@ modexp_div_E_and_2: 2 :MSTORE(array_div_short_inB) :CALL(array_div_short) - %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) $ => C :MLOAD(array_div_short_len_quo) C :MSTORE(modexp_Elen) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 2 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3 :JMPN(outOfCountersStep) modexp_quo_from_div_short: $ => A :MLOAD(array_div_short_quo + RR) @@ -244,7 +244,7 @@ modexp_pre_B_square: $ => C :MLOAD(modexp_Blen) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 1 :JMPN(outOfCountersStep) modexp_B_to_square1: $ => A :MLOAD(modexp_B + RR) @@ -254,14 +254,14 @@ modexp_B_to_square1: modexp_square_B: :CALL(array_square) - %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) $ => C :MLOAD(array_square_len_out) $ => D :MLOAD(modexp_Mlen) C - 1 => RR D - 1 => E - %MAX_CNT_STEPS - STEP - 4*C - 4*D - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) ; Compute B = (B^2) % M modexp_out_to_div2: @@ -277,13 +277,13 @@ modexp_M_to_div2: modexp_div_out_and_M1: :CALL(array_div) - %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) $ => C :MLOAD(array_div_len_rem) C :MSTORE(modexp_Blen) C - 1 => RR - %MAX_CNT_STEPS - STEP - 4*C - 1 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) modexp_rem_from_div3: $ => A :MLOAD(array_div_rem + RR) From 2f779d5397bce678beb708cb1a91c5e49f76e250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Masip?= Date: Wed, 20 Dec 2023 11:21:58 +0100 Subject: [PATCH 7/7] Link added to ecPairing --- main/precompiled/pre-ecPairing.zkasm | 1 + 1 file changed, 1 insertion(+) diff --git a/main/precompiled/pre-ecPairing.zkasm b/main/precompiled/pre-ecPairing.zkasm index fb592c6d..0386873a 100644 --- a/main/precompiled/pre-ecPairing.zkasm +++ b/main/precompiled/pre-ecPairing.zkasm @@ -7,6 +7,7 @@ * @process-precompiled * - stack input: [x1, y1, x2, y2, ..., xk, yk] * - stack output: [success] + * @note For implementation details, see: https://hackmd.io/kcEJAWISQ56eE6YpBnurgw?view */ funcEcPairing: