diff --git a/evm/src/bn254.rs b/evm/src/bn254.rs index 6c993d8c..8f29e12d 100644 --- a/evm/src/bn254.rs +++ b/evm/src/bn254.rs @@ -115,6 +115,27 @@ fn neg_fp(x: Fp) -> Fp { (BN_BASE - x) % BN_BASE } +fn exp_fp(x: Fp, e: U256) -> Fp { + let mut current = x; + let mut product = U256::one(); + + for j in 0..256 { + if e.bit(j) { + product = U256::try_from(product.full_mul(current) % BN_BASE).unwrap(); + } + current = U256::try_from(current.full_mul(current) % BN_BASE).unwrap(); + } + product +} + +fn inv_fp(x: Fp) -> Fp { + exp_fp(x, BN_BASE - 2) +} + +fn div_fp(x: Fp, y: Fp) -> Fp { + mul_fp(x, inv_fp(y)) +} + fn conj_fp2(a: Fp2) -> Fp2 { let [a, a_] = a; [a, neg_fp(a_)] @@ -246,23 +267,6 @@ pub fn frob_fp12(n: usize, f: Fp12) -> Fp12 { [frob_fp6(n, f0), mul_fp6(scale, frob_fp6(n, f1))] } -fn exp_fp(x: Fp, e: U256) -> Fp { - let mut current = x; - let mut product = U256::one(); - - for j in 0..256 { - if e.bit(j) { - product = U256::try_from(product.full_mul(current) % BN_BASE).unwrap(); - } - current = U256::try_from(current.full_mul(current) % BN_BASE).unwrap(); - } - product -} - -fn inv_fp(x: Fp) -> Fp { - exp_fp(x, BN_BASE - 2) -} - // fn inv_fp2(a: Fp2) -> Fp2 { // let [a0, a1] = a; // let norm = inv_fp(mul_fp(a0, a0) + mul_fp(a1, a1)); @@ -655,3 +659,69 @@ pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { mul_fp2(embed_fp2(cy), qy), ) } + +fn tangent_slope(p: Curve) -> Fp { + let [px, py] = p; + let num = mul_fp(mul_fp(px, px), U256::from(3)); + let denom = mul_fp(py, U256::from(2)); + div_fp(num, denom) +} + +fn cord_slope(p: Curve, q: Curve) -> Fp { + let [px, py] = p; + let [qx, qy] = q; + let num = sub_fp(qy, py); + let denom = sub_fp(qx, px); + div_fp(num, denom) +} + +fn third_point(m: Fp, p: Curve, q: Curve) -> Curve { + let [px, py] = p; + let [qx, _] = q; + let ox = sub_fp(mul_fp(m, m), add_fp(px, qx)); + let oy = sub_fp(mul_fp(m, sub_fp(px, ox)), py); + [ox, oy] +} + +fn curve_add(p: Curve, q: Curve) -> Curve { + if p == q { + curve_double(p) + } + else { + third_point(cord_slope(p, q), p, q) + } +} + +fn curve_double(p: Curve) -> Curve { + third_point(tangent_slope(p), p, p) +} + +const EXP: [usize; 253] = [ + 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, + 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { + let mut o = p; + let mut acc = embed_fp12(U256::one()); + let mut line; + + for i in EXP { + acc = mul_fp12(acc, acc); + line = tangent(o, q); + acc = mul_fp12(line, acc); + o = curve_double(o); + if i != 0 { + line = cord(p, o, q); + acc = mul_fp12(line, acc); + o = curve_add(p, o); + } + } + acc +} 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 e2b39c7c..0f860047 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 @@ -126,6 +126,12 @@ miller_zero_final: /// out = mul_fp12_sparse(out, line) /// O += O +global test_mul_tan: + // stack: out, f, retdest, 0xnm, times, O, P, Q, out + %store_fp12 + // stack: retdest, 0xnm, times, O, P, Q, out + %jump(mul_tangent) + mul_tangent: // stack: retdest, 0xnm, times, O, P, Q, out PUSH mul_tangent_2 DUP13 PUSH mul_tangent_1 @@ -154,7 +160,13 @@ mul_tangent_2: after_double: // stack: 2*O, retdest, 0xnm, times, O, P, Q, out {100: line} SWAP5 POP SWAP5 POP + // stack: retdest, 0xnm, times, 2*O, P, Q, out {100: line} + + %pop3 %pop2 %pop2 %pop4 + %load_fp12 + %jump(0xdeadbeef) + JUMP @@ -163,6 +175,12 @@ after_double: /// out = mul_fp12_sparse(out, line) /// O += P +global test_mul_cord: + // stack: out, f, 0xnm, times, O, P, Q, out + %store_fp12 + // stack: 0xnm, times, O, P, Q, out + %jump(mul_cord) + mul_cord: // stack: 0xnm, times, O, P, Q, out PUSH mul_cord_1 @@ -196,12 +214,6 @@ after_add: %jump(miller_one) -global test_cord: - // stack: p1x , p1y, p2x , p2y, qx, qx_, qy, qy_ - %cord - // stack: - %check(100) - /// def cord(p1x, p1y, p2x, p2y, qx, qy): /// return sparse_store( /// p1y*p2x - p2y*p1x, @@ -249,12 +261,6 @@ global test_cord: %endmacro -global test_tangent: - // stack: px, py, qx, qx_, qy, qy_ - %tangent - // stack: - %check(100) - /// def tangent(px, py, qx, qy): /// return sparse_store( /// py**2 - 9,