openvm_pairing_guest/halo2curves_shims/bn254/
line.rs

1extern crate std;
2
3use std::ops::{Add, Mul, Neg, Sub};
4
5use halo2curves_axiom::bn256::{Fq12, Fq2};
6use openvm_ecc_guest::{
7    algebra::{field::FieldExtension, Field},
8    AffinePoint,
9};
10
11use super::{Bn254, BN254_XI};
12use crate::pairing::{EvaluatedLine, LineMulDType};
13
14impl LineMulDType<Fq2, Fq12> for Bn254 {
15    /// Multiplies two lines in 013-form to get an element in 01234-form
16    fn mul_013_by_013(l0: &EvaluatedLine<Fq2>, l1: &EvaluatedLine<Fq2>) -> [Fq2; 5] {
17        let b0 = &l0.b;
18        let c0 = &l0.c;
19        let b1 = &l1.b;
20        let c1 = &l1.c;
21
22        // where w⁶ = xi
23        // l0 * l1 = 1 + (b0 + b1)w + (b0b1)w² + (c0 + c1)w³ + (b0c1 + b1c0)w⁴ + (c0c1)w⁶
24        //         = (1 + c0c1 * xi) + (b0 + b1)w + (b0b1)w² + (c0 + c1)w³ + (b0c1 + b1c0)w⁴
25        let x0 = Fq2::ONE + c0 * c1 * *BN254_XI;
26        let x1 = b0 + b1;
27        let x2 = b0 * b1;
28        let x3 = c0 + c1;
29        let x4 = b0 * c1 + b1 * c0;
30
31        [x0, x1, x2, x3, x4]
32    }
33
34    /// Multiplies a line in 013-form with a Fp12 element to get an Fp12 element
35    fn mul_by_013(f: &Fq12, l: &EvaluatedLine<Fq2>) -> Fq12 {
36        Self::mul_by_01234(f, &[Fq2::ONE, l.b, Fq2::ZERO, l.c, Fq2::ZERO])
37    }
38
39    /// Multiplies a line in 01234-form with a Fp12 element to get an Fp12 element
40    fn mul_by_01234(f: &Fq12, x: &[Fq2; 5]) -> Fq12 {
41        let fx = Fq12::from_coeffs([x[0], x[1], x[2], x[3], x[4], Fq2::ZERO]);
42        f * fx
43    }
44}
45
46/// Returns a line function for a tangent line at the point P
47#[allow(non_snake_case)]
48pub fn tangent_line_013<Fp, Fp2>(P: AffinePoint<Fp>) -> EvaluatedLine<Fp2>
49where
50    Fp: Field,
51    Fp2: Field + FieldExtension<Fp>,
52    for<'a> &'a Fp: Add<&'a Fp, Output = Fp>,
53    for<'a> &'a Fp: Sub<&'a Fp, Output = Fp>,
54    for<'a> &'a Fp: Mul<&'a Fp, Output = Fp>,
55    for<'a> &'a Fp2: Add<&'a Fp2, Output = Fp2>,
56    for<'a> &'a Fp2: Sub<&'a Fp2, Output = Fp2>,
57    for<'a> &'a Fp2: Mul<&'a Fp2, Output = Fp2>,
58    for<'a> &'a Fp2: Neg<Output = Fp2>,
59{
60    let one = Fp2::ONE;
61    let two = &one + &one;
62    let three = &one + &two;
63    let x = Fp2::embed(P.x);
64    let y = Fp2::embed(P.y);
65
66    // λ = (3x^2) / (2y)
67    // 1 - λ(x/y)w + (λx - y)(1/y)w^3
68    // b = -(λ * x / y)
69    //   = -3x^3 / 2y^2
70    // c = (λ * x - y) / y
71    //   = 3x^3/2y^2 - 1
72    let x_squared = &x * &x;
73    let x_cubed = x_squared * &x;
74    let y_squared = &y * &y;
75    let three_x_cubed = &three * &x_cubed;
76    let over_two_y_squared = Fp2::ONE.div_unsafe(&(&two * &y_squared));
77
78    let b = (&three_x_cubed).neg() * &over_two_y_squared;
79    let c = &three_x_cubed * &over_two_y_squared - Fp2::ONE;
80
81    EvaluatedLine { b, c }
82}