arnaucube
arnaucube/ark-curves-cherry-pickedPublic Self-hosted repository
ark-curves-cherry-picked/cp6_782/src/curves/mod.rs
cp6_782/src/curves/mod.rsRaw
  1use ark_ec::{models::short_weierstrass::SWCurveConfig, PairingEngine};
  2use ark_ff::{
  3    biginteger::BigInteger832,
  4    fields::{BitIteratorBE, Field},
  5    BigInt, CyclotomicMultSubgroup, One,
  6};
  7
  8use crate::{Fq, Fq3, Fq6, Fr};
  9
 10pub mod g1;
 11pub use self::g1::{G1Affine, G1Projective};
 12
 13pub mod g2;
 14pub use self::g2::{G2Affine, G2Projective};
 15
 16#[cfg(test)]
 17mod tests;
 18
 19pub type GT = Fq6;
 20
 21#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 22pub struct CP6_782;
 23
 24impl PairingEngine for CP6_782 {
 25    type Fr = Fr;
 26    type G1Projective = G1Projective;
 27    type G1Affine = G1Affine;
 28    type G1Prepared = G1Affine;
 29    type G2Projective = G2Projective;
 30    type G2Affine = G2Affine;
 31    type G2Prepared = G2Affine;
 32    type Fq = Fq;
 33    type Fqe = Fq3;
 34    type Fqk = Fq6;
 35
 36    fn miller_loop<'a, I>(i: I) -> Self::Fqk
 37    where
 38        I: IntoIterator<Item = &'a (Self::G1Prepared, Self::G2Prepared)>,
 39    {
 40        let mut result = Self::Fqk::one();
 41        for &(ref p, ref q) in i {
 42            result *= &CP6_782::ate_miller_loop(p, q);
 43        }
 44        result
 45    }
 46
 47    fn final_exponentiation(r: &Self::Fqk) -> Option<Self::Fqk> {
 48        Some(CP6_782::final_exponentiation(r))
 49    }
 50}
 51
 52impl CP6_782 {
 53    pub fn ate_pairing(p: &G1Affine, q: &G2Affine) -> GT {
 54        CP6_782::final_exponentiation(&CP6_782::ate_miller_loop(p, q))
 55    }
 56
 57    fn ate_miller_loop(p: &G1Affine, q: &G2Affine) -> Fq6 {
 58        let px = p.x;
 59        let py = p.y;
 60        let qx = q.x;
 61        let qy = q.y;
 62        let mut py_twist_squared = TWIST.square();
 63        py_twist_squared.mul_assign_by_fp(&py);
 64
 65        let mut old_rx;
 66        let mut old_ry;
 67        let mut rx = qx;
 68        let mut ry = qy;
 69        let mut f = Fq6::one();
 70
 71        // The for loop is executed for all bits (EXCEPT the MSB itself) of
 72        // cp6_782_param_p (skipping leading zeros) in MSB to LSB order
 73        for bit in BitIteratorBE::without_leading_zeros(ATE_LOOP_COUNT).skip(1) {
 74            old_rx = rx;
 75            old_ry = ry;
 76
 77            let old_rx_square = old_rx.square();
 78            let old_rx_square_3 = old_rx_square.double() + &old_rx_square;
 79            let old_rx_square_3_a = old_rx_square_3 + &g2::Parameters::COEFF_A;
 80            let old_ry_double_inverse = old_ry.double().inverse().unwrap();
 81
 82            let gamma = old_rx_square_3_a * &old_ry_double_inverse;
 83            let gamma_twist = gamma * &TWIST;
 84            let gamma_old_rx = gamma * &old_rx;
 85            let mut gamma_twist_px = gamma_twist;
 86            gamma_twist_px.mul_assign_by_fp(&px);
 87
 88            let x = py_twist_squared;
 89            let y = gamma_old_rx - &old_ry - &gamma_twist_px;
 90            let ell_rr_at_p: Fq6 = Fq6::new(x, y);
 91
 92            rx = gamma.square() - &old_rx.double();
 93            ry = gamma * &(old_rx - &rx) - &old_ry;
 94            f = f.square() * &ell_rr_at_p;
 95
 96            if bit {
 97                old_rx = rx;
 98                old_ry = ry;
 99
100                let gamma = (old_ry - &qy) * &((old_rx - &qx).inverse().unwrap());
101                let gamma_twist = gamma * &TWIST;
102                let gamma_qx = gamma * &qx;
103                let mut gamma_twist_px = gamma_twist;
104                gamma_twist_px.mul_assign_by_fp(&px);
105
106                let x = py_twist_squared;
107                let y = gamma_qx - &qy - &gamma_twist_px;
108                let ell_rq_at_p: Fq6 = Fq6::new(x, y);
109
110                rx = gamma.square() - &old_rx - &qx;
111                ry = gamma * &(old_rx - &rx) - &old_ry;
112                f = f * &ell_rq_at_p;
113            }
114        }
115        f
116    }
117
118    fn final_exponentiation(value: &Fq6) -> GT {
119        let value_inv = value.inverse().unwrap();
120        let value_to_first_chunk = CP6_782::final_exponentiation_first(value, &value_inv);
121        let value_inv_to_first_chunk = CP6_782::final_exponentiation_first(&value_inv, value);
122        CP6_782::final_exponentiation_last(&value_to_first_chunk, &value_inv_to_first_chunk)
123    }
124
125    fn final_exponentiation_first(elt: &Fq6, elt_inv: &Fq6) -> Fq6 {
126        // (q^3-1)*(q+1)
127
128        // elt_q3 = elt^(q^3)
129        let mut elt_q3 = elt.clone();
130        elt_q3.frobenius_map(3);
131        // elt_q3_over_elt = elt^(q^3-1)
132        let elt_q3_over_elt = elt_q3 * elt_inv;
133        // alpha = elt^((q^3-1) * q)
134        let mut alpha = elt_q3_over_elt.clone();
135        alpha.frobenius_map(1);
136        // beta = elt^((q^3-1)*(q+1)
137        alpha * &elt_q3_over_elt
138    }
139
140    fn final_exponentiation_last(elt: &Fq6, elt_inv: &Fq6) -> Fq6 {
141        let mut elt_q = elt.clone();
142        elt_q.frobenius_map(1);
143
144        let w1_part = elt_q.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_W1);
145        let w0_part = if FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG {
146            elt_inv.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0)
147        } else {
148            elt.cyclotomic_exp(&FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0)
149        };
150
151        w1_part * &w0_part
152    }
153}
154
155/// TWIST = (0, 1, 0)
156pub const TWIST: Fq3 = Fq3::new(Fq::ZERO, Fq::ONE, Fq::ZERO);
157
158/// ATE_IS_LOOP_COUNT_NEG = false
159pub const ATE_IS_LOOP_COUNT_NEG: bool = false;
160
161/// ATE_LOOP_COUNT =
162/// 506464946133393486072777102926336625944849939610982267859828541006717966526573193706126370441346337661774335955699621
163pub const ATE_LOOP_COUNT: [u64; 13] = [
164    0x55c5b9b57b942ae8,
165    0x3d52287d3dfd424a,
166    0xcf1ff9d6a543deb7,
167    0x820c9c5711ceeebc,
168    0x549a2d44305d20fe,
169    0x50f5c131afd70235,
170    0xab3596c8617c5792,
171    0x830c728d80f9d78b,
172    0x6a7223ee72023d07,
173    0xbc5d176b746af026,
174    0xe959283d8f526663,
175    0xc4d2263babf8941f,
176    0x3848,
177];
178
179/// FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG = true
180pub const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool = true;
181
182/// FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0 =
183/// 7000705447348627246181409558336018323010329260726930841638672011287206690002601216854775649561085256265269640040570922609783227469279331691880282815325569032149343779036142830666859805506518426649197067288711084398033
184pub const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: BigInteger832 = BigInt::new([
185    0xb62ef36af72855d1,
186    0x676b5cef49d290fa,
187    0xd17fcf3c60947427,
188    0x5b93d992bc1b2849,
189    0x2171887cecd072cb,
190    0x879a2873f1516f4a,
191    0x8cc6856bd2cdf24e,
192    0xbff4fb6644d01993,
193    0x5dcbeea3e31ea667,
194    0x5f256f47681649f3,
195    0x2355a2b0839967fe,
196    0x144ed,
197    0x0,
198]);
199
200/// FINAL_EXPONENT_LAST_CHUNK_W1 =
201/// 86482221941698704497288378992285180119495364068003923046442785886272123124361700722982503222189455144364945735564951562986
202pub const FINAL_EXPONENT_LAST_CHUNK_W1: BigInteger832 = BigInt::new([
203    0x5657b9b57b942aea,
204    0x84f9a65f3bd54eaf,
205    0x5ea4214e35cd127,
206    0xe3cbcbc14ec1501d,
207    0xf196cb845a3092ab,
208    0x7e14627ad0e19017,
209    0x217db4,
210    0x0,
211    0x0,
212    0x0,
213    0x0,
214    0x0,
215    0x0,
216]);