diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 9c4956c2..2df002c1 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -110,34 +110,34 @@ pub fn gen_fp12_sparse() -> Fp12 { sparse_embed(gen_fp(), gen_fp2(), gen_fp2()) } -/// The output T of the miller loop is not an invariant, -/// but one gets an invariant by raising T to the power +/// The output y of the miller loop is not an invariant, +/// but one gets an invariant by raising y to the power /// (p^12 - 1)/N = (p^6 - 1)(p^2 + 1)(p^4 - p^2 + 1)/N /// where N is the cyclic group order of the curve. -/// To achieve this, we first exponentiate T by p^6 - 1 via -/// T = T_6 / T +/// To achieve this, we first exponentiate y by p^6 - 1 via +/// y = y_6 / y /// and then exponentiate the result by p^2 + 1 via -/// T = T_2 * T +/// y = y_2 * y /// We then note that (p^4 - p^2 + 1)/N can be rewritten as /// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0 /// where 0 < a0, a1, a2 < p. Then the final power is given by -/// T = T_3 * (T^a2)_2 * (T^-a1)_1 * (T^-a0) +/// y = y_3 * (y^a2)_2 * (y^-a1)_1 * (y^-a0) pub fn invariance_inducing_power(f: Fp12) -> Fp12 { - let mut t = f.frob(6) / f; - t = t.frob(2) * t; - let (t_a2, t_a1, t_a0) = get_powers(t); - t.frob(3) * t_a2.frob(2) * t_a1.frob(1) * t_a0 + let mut y = f.frob(6) / f; + y = y.frob(2) * y; + let (y_a2, y_a1, y_a0) = get_custom_powers(y); + y.frob(3) * y_a2.frob(2) * y_a1.frob(1) * y_a0 } /// Given an f: Fp12, this function computes -/// T^a2, T^(-a1), T^(-a0) +/// y^a2, y^(-a1), y^(-a0) /// by first computing -/// T^a4, T^a2, T^a0 +/// y^a4, y^a2, y^a0 /// where a1 is given by /// a1 = a4 + 2a2 - a0 -/// thus what remains is inverting T^a0 and returning -/// T^a2, T^a4 * T^a2 * T^a2 * T^(-a0), T^(-a0) -fn get_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { +/// thus what remains is inverting y^a0 and returning +/// y^a2, y^a4 * y^a2 * y^a2 * y^(-a0), y^(-a0) +fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { const EXPS4: [(usize, usize, usize); 64] = [ (1, 1, 0), (1, 1, 1), diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index c74baa65..440ee49c 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -27,13 +27,13 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_add.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_mul.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/final_power.asm"), include_str!("asm/curve/bn254/curve_arithmetic/miller_loop.asm"), include_str!("asm/curve/bn254/curve_arithmetic/tate_pairing.asm"), include_str!("asm/curve/bn254/field_arithmetic/inverse.asm"), include_str!("asm/curve/bn254/field_arithmetic/fp6_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/fp12_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/frobenius.asm"), - include_str!("asm/curve/bn254/field_arithmetic/power.asm"), include_str!("asm/curve/bn254/field_arithmetic/util.asm"), include_str!("asm/curve/common.asm"), include_str!("asm/curve/secp256k1/curve_mul.asm"), diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_power.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_power.asm new file mode 100644 index 00000000..e790a261 --- /dev/null +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_power.asm @@ -0,0 +1,229 @@ +/// def final_exp(y): +/// y0, y4, y2 = 1, 1, 1 +/// power_loop_4() +/// power_loop_2() +/// power_loop_0() +/// custom_powers() +/// final_power() +/// +/// def custom_powers() +/// y0 = y0^{-1} +/// y1 = y4 * y2^2 * y0 +/// return y2, y1, y0 +/// +/// def final_power() +/// y = y.frob(3) +/// y2 = y2.frob(2) +/// y1 = y1.frob(1) +/// return y * y2 * y4 * y0 + +global final_exp: + // stack: val, retdest + %stack () -> (1, 1, 1) + // stack: 1, 1, 1, val, retdest + %mstore_kernel_general(200) + %mstore_kernel_general(224) + %mstore_kernel_general(212) + // stack: val, retdest {200: y0, 212: y2, 224: y4} + stack () -> 64, 62, 65 + // stack: 64, 62, 65, val, retdest {200: y0, 212: y2, 224: y4} + %jump(power_loop_4) + +custom_powers: + // stack: val, retdest {200: y0, 212: y2, 224: y4} + %stack () -> (200, 236, make_y1_1) + // stack: 200, 236, make_y1_1, val, retdest {200: y0, 212: y2, 224: y4} + %jump(inv_fp12) +make_y1_1: + // stack: val, retdest {236: y0^-1, 212: y2, 224: y4} + %stack () -> (212, 224, 224, make_y1_2) + // stack: 212, 224, 224, make_y1_2, val, retdest {236: y0^-1, 212: y2, 224: y4} + %jump(mul_fp12) +make_y1_2: + // stack: val, retdest {236: y0^-1, 212: y2, 224: y4 * y2} + %stack () -> (212, 224, 224, make_y1_3) + // stack: 212, 224, 224, make_y1_3, val, retdest {236: y0^-1, 212: y2, 224: y4 * y2} + %jump(mul_fp12) +make_y1_3: + // stack: val, retdest {236: y0^-1, 212: y2, 224: y4 * y2^2} + %stack () -> (236, 224, 224, final_power) + // stack: 236, 224, 224, final_power, val, retdest {236: y0^-1, 212: y2, 224: y4 * y2^2} + %jump(mul_fp12) + +final_power: + // stack: val, retdest {val: y , 212: y^a2 , 224: y^a1 , 236: y^a0} + %frob_fp12_3 + // stack: val, retdest {val: y_3, 212: y^a2 , 224: y^a1 , 236: y^a0} + %stack () -> (212, 212) + %frob_fp12_2_ + POP + // stack: val, retdest {val: y_3, 212: (y^a2)_2, 224: y^a1 , 236: y^a0} + PUSH 224 + %frob_fp12_1 + POP + // stack: val, retdest {val: y_3, 212: (y^a2)_2, 224: (y^a1)_1, 236: y^a0} + %stack (val) -> (212, val, val, penult_mul, val) + // stack: 212, val, val, penult_mul, val, retdest {val: y_3, 212: (y^a2)_2, 224: (y^a1)_1, 236: y^a0} + %jump(mul_fp12) +penult_mul: + // stack: val, retdest {val: y_3 * (y^a2)_2, 224: (y^a1)_1, 236: y^a0} + %stack (val) -> (224, val, val, final_mul, val) + // stack: 224, val, val, final_mul, val, retdest {val: y_3 * (y^a2)_2, 224: (y^a1)_1, 236: y^a0} + %jump(mul_fp12) +final_mul: + // stack: val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 236: y^a0} + %stack (val) -> (236, val, val) + // stack: 236, val, val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 236: y^a0} + %jump(mul_fp12) + + +/// def power_loop_4(): +/// for i in range(64): +/// abc = load(i, power_data_4) +/// if a: +/// y4 *= acc +/// if b: +/// y2 *= acc +/// if c: +/// y0 *= acc +/// acc = square_fp12(acc) +/// y4 *= acc +/// +/// def power_loop_2(): +/// for i in range(62): +/// ab = load(i, power_data_2) +/// if a: +/// y2 *= acc +/// if b: +/// y0 *= acc +/// acc = square_fp12(acc) +/// y2 *= acc +/// +/// def power_loop_0(): +/// for i in range(65): +/// a = load(i, power_data_0) +/// if a: +/// y0 *= acc +/// acc = square_fp12(acc) +/// y0 *= acc + +power_loop_4: + // stack: i , j, k, val {200: y0, 212: y2, 224: y4} + DUP1 ISZERO + // stack: break?, i , j, k, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_4_end) + // stack: i , j, k, val {200: y0, 212: y2, 224: y4} + %sub_const(1) + // stack: i-1, j, k, val {200: y0, 212: y2, 224: y4} + DUP1 %mload_kernel_code(power_data_4) + // stack: abc, i-1, j, k, val {200: y0, 212: y2, 224: y4} + DUP1 %lt_const(100) + // stack: skip?, abc, i-1, j, k, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_4_b) + // stack: abc, i-1, j, k, val {200: y0, 212: y2, 224: y4} + %sub_const(100) + // stack: bc, i-1, j, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_4_b PUSH 224 DUP1 DUP8 + // stack: val, 224, 224, power_loop_4_b, bc, i-1, j, k, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) +power_loop_4_b: + // stack: bc, i, j, k, val {200: y0, 212: y2, 224: y4} + DUP1 %lt_const(10) + // stack: skip?, bc, i, j, k, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_4_c) + // stack: bc, i, j, k, val {200: y0, 212: y2, 224: y4} + %sub_const(10) + // stack: c, i, j, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_4_c PUSH 212 DUP1 DUP8 + // stack: val, 212, 212, power_loop_4_c, c, i, j, k, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) +power_loop_4_c: + // stack: c, i, j, k, val {200: y0, 212: y2, 224: y4} + ISZERO + // stack: skip?, i, j, k, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_4_sq) + // stack: i, j, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_4_sq PUSH 200 DUP1 DUP7 + // stack: val, 200, 200, power_loop_4_sq, i, j, k, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) +power_loop_4_sq: + // stack: i, j, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_4 DUP5 DUP1 + // stack: val, val, power_loop_4, i, j, k, val {200: y0, 212: y2, 224: y4} + %jump(square_fp12) +power_loop_4_end: + // stack: 0, j, k, val {200: y0, 212: y2, 224: y4} + POP + // stack: j, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_2 PUSH 224 DUP1 DUP6 + // stack: val, 224, 224, power_loop_2, j, k, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) + +power_loop_2: + // stack: j , k, val {200: y0, 212: y2, 224: y4} + DUP1 ISZERO + // stack: break?, j , k, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_2_end) + // stack: j , k, val {200: y0, 212: y2, 224: y4} + %sub_const(1) + // stack: j-1, k, val {200: y0, 212: y2, 224: y4} + DUP1 %mload_kernel_code(power_data_2) + // stack: ab, j-1, k, val {200: y0, 212: y2, 224: y4} + DUP1 %lt_const(10) + // stack: skip?, ab, j-1, k, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_2_b) + // stack: ab, j-1, k, val {200: y0, 212: y2, 224: y4} + %sub_const(10) + // stack: b, j-1, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_2_b PUSH 212 DUP1 DUP7 + // stack: val, 212, 212, power_loop_2_b, b, j-1, k, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) +power_loop_2_b: + // stack: b, j, k, val {200: y0, 212: y2, 224: y4} + ISZERO + // stack: skip?, j, k, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_2_sq) + // stack: j, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_2_sq PUSH 200 DUP1 DUP6 + // stack: val, 200, 200, power_loop_2_sq, j, k, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) +power_loop_2_sq: + // stack: j, k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_2 DUP4 DUP1 + // stack: val, val, power_loop_2, j, k, val {200: y0, 212: y2, 224: y4} + %jump(square_fp12) +power_loop_2_end: + // stack: 0, k, val {200: y0, 212: y2, 224: y4} + POP + // stack: k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_0 PUSH 212 DUP1 DUP5 + // stack: val, 212, 212, power_loop_0, k, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) + +power_loop_0: + // stack: k , val {200: y0, 212: y2, 224: y4} + DUP1 ISZERO + // stack: break?, k , val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_0_end) + // stack: k , val {200: y0, 212: y2, 224: y4} + %sub_const(1) + // stack: k-1, val {200: y0, 212: y2, 224: y4} + DUP1 %mload_kernel_code(power_data_0) + // stack: a, k-1, val {200: y0, 212: y2, 224: y4} + ISZERO + // stack: skip?, k-1, val {200: y0, 212: y2, 224: y4} + %jumpi(power_loop_0_sq) + // stack: k-1, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_0_sq PUSH 200 DUP1 DUP5 + // stack: val, 200, 200, power_loop_0_sq, k-1, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) +power_loop_0_sq: + // stack: k, val {200: y0, 212: y2, 224: y4} + PUSH power_loop_0 DUP3 DUP1 + // stack: val, val, power_loop_0, k, val {200: y0, 212: y2, 224: y4} + %jump(square_fp12) +power_loop_0_end: + // stack: 0, val {200: y0, 212: y2, 224: y4} + %stack (i, val) -> (200, val, 200, custom_powers, val) + // stack: 200, val, 200, custom_powers, val {200: y0, 212: y2, 224: y4} + %jump(mul_fp12) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm index aa341288..0c92143b 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm @@ -25,7 +25,7 @@ /// 0xnm -= 1 /// mul_tangent() -global miller_init: +global miller: // stack: ptr, out, retdest PUSH 1 // stack: 1, ptr, out, retdest diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm index fe46a9e7..198d7b0e 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm @@ -1,74 +1,38 @@ /// def tate(P: Curve, Q: TwistedCurve) -> Fp12: /// out = miller_loop(P, Q) -/// out = out.frob(6) / out -/// out = out.frob(2) * out -/// return final_power(out) - +/// return make_invariant(P, Q) global tate: - // stack: ptr, out, retdest - DUP2 - // stack: out, ptr, out, retdest - PUSH post_miller - // stack: post_miller, out, ptr, out, retdest - SWAP2 - // stack: ptr, out, post_miller, out, retdest - %jump(miller_init) -global post_miller: - // stack: out, retdest - PUSH tate_mul_1 - // stack: tate_mul_1, out, retdest - PUSH 100 - // stack: 100, tate_mul_1, out, retdest - DUP3 - // stack: out, 100, tate_mul_1, out, retdest + // stack: inp, out, retdest + %stack (inp, out) -> (inp, out, make_invariant, out) + // stack: inp, out, make_invariant, out, retdest + %jump(miller) + + +/// def make_invariant(y: Fp12): +/// y = first_exp(y) +/// y = second_exp(y) +/// return final_exponentiation(y) +global make_invariant: +/// def first_exp(t): +/// return t.frob(6) / t + // stack: out, retdest {out: y} + %stack (out) -> (out, 100, first_exp, out) + // stack: out, 100, first_exp, out, retdest {out: y} %jump(inv_fp12) -tate_mul_1: - // stack: out, retdest {100: inv} +global first_exp: + // stack: out, retdest {out: y , 100: y^-1} %frob_fp12_6 - // stack: out, retdest {100: inv} - PUSH tate_mul_2 - // stack: tate_mul_2, out, retdest {100: inv} - DUP2 - // stack: out, tate_mul_2, out, retdest {100: inv} - PUSH 100 - // stack: 100, out, tate_mul_2, out, retdest {100: inv} - DUP2 - // stack: out, 100, out, tate_mul_2, out, retdest {100: inv} + // stack: out, retdest {out: y_6, 100: y^-1} + %stack (out) -> (out, 100, out, second_exp, out) + // stack: out, 100, out, second_exp, out, retdest {out: y_6, 100: y^-1} %jump(mul_fp12) -tate_mul_2: - // stack: out, retdest {100: inv} - PUSH tate_power - // stack: tate_power, out, retdest {100: inv} - DUP2 - // stack: out, tate_power, out, retdest {100: inv} - PUSH 100 - // stack: 100, out, tate_power, out, retdest {100: inv} - DUP2 - // stack: out, 100, out, tate_power, out, retdest {100: inv} + +/// def second_exp(t): +/// return t.frob(2) * t +global second_exp: + // stack: out, retdest {out: y} + %stack (out) -> (out, 100, out, final_exp, out) + // stack: out, 100, out, final_exp, out, retdest {out: y} %frob_fp12_2_ - // stack: 100, out, tate_power, out, retdest {100: acc} - DUP2 - // stack: out, 100, out, tate_power, out, retdest {100: acc} - %jump(mul_fp12) -tate_power: - // stack: out, retdest {100: acc} - PUSH tate_return - // stack: tate_return, out, retdest {100: acc} - PUSH 100 - // stack: 100, tate_return, out, retdest {100: acc} - PUSH 300 - // stack: 300, 100, tate_return, out, retdest {100: acc} - DUP4 - // stack: out, 300, 100, tate_return, out, retdest {100: acc} - %move_fp12 - // stack: 300, 100, tate_return, out, retdest {100: acc, 300: out} - %jump(power) -tate_return: - // stack: out, retdest {100: pow} - PUSH 100 - // stack: 100, out, retdest {100: pow} - DUP2 - // stack: out, 100, out, retdest {100: pow} - %frob_fp12_3 - // stack: out, 100, out, retdest {100: pow} + // stack: 100, out, final_exp, out, retdest {out: y, 100: y_2} %jump(mul_fp12) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/power.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/power.asm deleted file mode 100644 index 51a122c0..00000000 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/power.asm +++ /dev/null @@ -1,223 +0,0 @@ -/// def invariance_inducing_power(acc): -/// power_init() -/// power_loop_4() -/// power_loop_2() -/// power_loop_0() -/// power_return() -/// -/// def power_init() -/// y0, y4, y2 = 1, 1, 1 -/// -/// def power_return() -/// y0 = y0^{-1} -/// y4 *= y0 * (y2**2) -/// y4 = frob_fp12_1(y4) -/// y2 = frob_fp12_2_(y2) -/// return y2 * y4 * y0 - -global power: - // stack: ptr, out, retdest - PUSH 1 DUP1 DUP1 - // stack: 1, 1, 1, ptr, out, retdest - %mstore_kernel_general(200) %mstore_kernel_general(224) %mstore_kernel_general(212) - // stack: ptr, out, retdest {200: y0, 212: y2, 224: y4} - PUSH 65 PUSH 62 PUSH 64 - // stack: 64, 62, 65, ptr, out, retdest {200: y0, 212: y2, 224: y4} - %jump(power_loop_4) - -power_return: - // stack: out, retdest {200: y0, 212: y2, 224: y4} - PUSH power_return_1 PUSH 236 PUSH 200 - // stack: 200, 236, power_return_1, out, retdest {200: y0, 212: y2, 224: y4} - %jump(inv_fp12) -power_return_1: - // stack: out, retdest {236: y0, 212: y2, 224: y4} - PUSH power_return_2 PUSH 224 DUP1 PUSH 212 - // stack: 212, 224, 224, power_return_2, out, retdest {236: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_return_2: - // stack: out, retdest {236: y0, 212: y2, 224: y4} - PUSH power_return_3 PUSH 224 DUP1 PUSH 212 - // stack: 212, 224, 224, power_return_3, out, retdest {236: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_return_3: - // stack: out, retdest {236: y0, 212: y2, 224: y4} - PUSH power_return_4 PUSH 224 DUP1 PUSH 236 - // stack: 236, 224, 224, power_return_4, out, retdest {236: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_return_4: - // stack: out, retdest {236: y0, 212: y2, 224: y4} - PUSH 224 - // stack: 224, out, retdest {236: y0, 212: y2, 224: y4} - %frob_fp12_1 - // stack: 224, out, retdest {236: y0, 212: y2, 224: y4} - POP - // stack: out, retdest {236: y0, 212: y2, 224: y4} - PUSH 212 DUP1 - // stack: 212, 212, out, retdest {236: y0, 212: y2, 224: y4} - %frob_fp12_2_ - // stack: 212, out, retdest {236: y0, 212: y2, 224: y4} - POP - // stack: out, retdest {236: y0, 212: y2, 224: y4} - PUSH power_return_5 DUP2 PUSH 236 PUSH 224 - // stack: 224, 236, out, power_return_5, out, retdest {236: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_return_5: - // stack: out, retdest {236: y0, 212: y2, 224: y4} - PUSH 212 DUP2 - // stack: out, 212, out, retdest {236: y0, 212: y2, 224: y4} - %jump(mul_fp12) - - -/// def power_loop_4(): -/// for i in range(64): -/// abc = load(i, power_data_4) -/// if a: -/// y4 *= acc -/// if b: -/// y2 *= acc -/// if c: -/// y0 *= acc -/// acc = square_fp12(acc) -/// y4 *= acc -/// -/// def power_loop_2(): -/// for i in range(62): -/// ab = load(i, power_data_2) -/// if a: -/// y2 *= acc -/// if b: -/// y0 *= acc -/// acc = square_fp12(acc) -/// y2 *= acc -/// -/// def power_loop_0(): -/// for i in range(65): -/// a = load(i, power_data_0) -/// if a: -/// y0 *= acc -/// acc = square_fp12(acc) -/// y0 *= acc - -power_loop_4: - // stack: i , j, k, ptr {200: y0, 212: y2, 224: y4} - DUP1 ISZERO - // stack: break?, i , j, k, ptr {200: y0, 212: y2, 224: y4} - %jumpi(power_loop_4_end) - // stack: i , j, k, ptr {200: y0, 212: y2, 224: y4} - %sub_const(1) - // stack: i-1, j, k, ptr {200: y0, 212: y2, 224: y4} - DUP1 %mload_kernel_code(power_data_4) - // stack: abc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4} - DUP1 %lt_const(100) - // stack: skip?, abc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4} - %jumpi(power_loop_4_b) - // stack: abc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4} - %sub_const(100) - // stack: bc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_4_b PUSH 224 DUP1 DUP8 - // stack: ptr, 224, 224, power_loop_4_b, bc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_loop_4_b: - // stack: bc, i, j, k, ptr {200: y0, 212: y2, 224: y4} - DUP1 %lt_const(10) - // stack: skip?, bc, i, j, k, ptr {200: y0, 212: y2, 224: y4} - %jumpi(power_loop_4_c) - // stack: bc, i, j, k, ptr {200: y0, 212: y2, 224: y4} - %sub_const(10) - // stack: c, i, j, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_4_c PUSH 212 DUP1 DUP8 - // stack: ptr, 212, 212, power_loop_4_c, c, i, j, k, ptr {200: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_loop_4_c: - // stack: c, i, j, k, ptr {200: y0, 212: y2, 224: y4} - ISZERO - // stack: skip?, i, j, k, ptr {200: y0, 212: y2, 224: y4} - %jumpi(power_loop_4_sq) - // stack: i, j, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_4_sq PUSH 200 DUP1 DUP7 - // stack: ptr, 200, 200, power_loop_4_sq, i, j, k, ptr {200: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_loop_4_sq: - // stack: i, j, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_4 DUP5 DUP1 - // stack: ptr, ptr, power_loop_4, i, j, k, ptr {200: y0, 212: y2, 224: y4} - %jump(square_fp12) -power_loop_4_end: - // stack: 0, j, k, ptr {200: y0, 212: y2, 224: y4} - POP - // stack: j, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_2 PUSH 224 DUP1 DUP6 - // stack: ptr, 224, 224, power_loop_2, j, k, ptr {200: y0, 212: y2, 224: y4} - %jump(mul_fp12) - -power_loop_2: - // stack: j , k, ptr {200: y0, 212: y2, 224: y4} - DUP1 ISZERO - // stack: break?, j , k, ptr {200: y0, 212: y2, 224: y4} - %jumpi(power_loop_2_end) - // stack: j , k, ptr {200: y0, 212: y2, 224: y4} - %sub_const(1) - // stack: j-1, k, ptr {200: y0, 212: y2, 224: y4} - DUP1 %mload_kernel_code(power_data_2) - // stack: ab, j-1, k, ptr {200: y0, 212: y2, 224: y4} - DUP1 %lt_const(10) - // stack: skip?, ab, j-1, k, ptr {200: y0, 212: y2, 224: y4} - %jumpi(power_loop_2_b) - // stack: ab, j-1, k, ptr {200: y0, 212: y2, 224: y4} - %sub_const(10) - // stack: b, j-1, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_2_b PUSH 212 DUP1 DUP7 - // stack: ptr, 212, 212, power_loop_2_b, b, j-1, k, ptr {200: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_loop_2_b: - // stack: b, j, k, ptr {200: y0, 212: y2, 224: y4} - ISZERO - // stack: skip?, j, k, ptr {200: y0, 212: y2, 224: y4} - %jumpi(power_loop_2_sq) - // stack: j, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_2_sq PUSH 200 DUP1 DUP6 - // stack: ptr, 200, 200, power_loop_2_sq, j, k, ptr {200: y0, 212: y2, 224: y4} - %jump(mul_fp12) -power_loop_2_sq: - // stack: j, k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_2 DUP4 DUP1 - // stack: ptr, ptr, power_loop_2, j, k, ptr {200: y0, 212: y2, 224: y4} - %jump(square_fp12) -power_loop_2_end: - // stack: 0, k, ptr {200: y0, 212: y2, 224: y4} - POP - // stack: k, ptr {200: y0, 212: y2, 224: y4} - PUSH power_loop_0 PUSH 212 DUP1 DUP5 - // stack: ptr, 212, 212, power_loop_0, k, ptr {200: y0, 212: y2, 224: y4} - %jump(mul_fp12) - -power_loop_0: - // stack: k , ptr - DUP1 ISZERO - // stack: break?, k , ptr - %jumpi(power_loop_0_end) - // stack: k , ptr - %sub_const(1) - // stack: k-1, ptr - DUP1 %mload_kernel_code(power_data_0) - // stack: a, k-1, ptr - ISZERO - // stack: skip?, k-1, ptr - %jumpi(power_loop_0_sq) - // stack: k-1, ptr - PUSH power_loop_0_sq PUSH 200 DUP1 DUP5 - // stack: ptr, 200, 200, power_loop_0_sq, k-1, ptr - %jump(mul_fp12) -power_loop_0_sq: - // stack: k, ptr - PUSH power_loop_0 DUP3 DUP1 - // stack: ptr, ptr, power_loop_0, k, ptr - %jump(square_fp12) -power_loop_0_end: - // stack: 0, ptr - POP - // stack: ptr - PUSH 200 PUSH power_return SWAP2 DUP2 - // stack: 200, ptr, 200, power_return - %jump(mul_fp12)