arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/groups/curves/short_weierstrass/bls12/mod.rs
r1cs-std/src/groups/curves/short_weierstrass/bls12/mod.rsRaw
  1use algebra::{
  2    curves::bls12::{Bls12Parameters, G1Prepared, TwistType},
  3    fields::Field,
  4    BitIterator, ProjectiveCurve,
  5};
  6use r1cs_core::{ConstraintSystem, SynthesisError};
  7
  8
  9use crate::prelude::*;
 10use crate::fields::{fp::FpGadget, fp2::Fp2Gadget, FieldGadget};
 11use crate::groups::curves::short_weierstrass::AffineGadget;
 12
 13use std::fmt::Debug;
 14
 15pub mod bls12_377;
 16
 17pub type G1Gadget<P> = AffineGadget<<P as Bls12Parameters>::G1Parameters, <P as Bls12Parameters>::Fp, FpGadget<<P as Bls12Parameters>::Fp>>;
 18pub type G2Gadget<P> = AffineGadget<<P as Bls12Parameters>::G2Parameters, <P as Bls12Parameters>::Fp, Fp2G<P>>;
 19
 20#[derive(Derivative)]
 21#[derivative(
 22    Clone(bound = "G1Gadget<P>: Clone"),
 23    Debug(bound = "G1Gadget<P>: Debug")
 24)]
 25pub struct G1PreparedGadget<P: Bls12Parameters>(pub G1Gadget<P>);
 26
 27impl<P: Bls12Parameters> G1PreparedGadget<P> {
 28    pub fn get_value(&self) -> Option<G1Prepared<P>> {
 29        Some(G1Prepared::from_affine(
 30            self.0.get_value().unwrap().into_affine(),
 31        ))
 32    }
 33
 34    pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
 35        _cs: CS,
 36        q: &G1Gadget<P>,
 37    ) -> Result<Self, SynthesisError> {
 38        Ok(G1PreparedGadget(q.clone()))
 39    }
 40}
 41
 42impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
 43    #[inline]
 44    fn to_bytes<CS: ConstraintSystem<P::Fp>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
 45        self.0.to_bytes(&mut cs.ns(|| "g_alpha to bytes"))
 46    }
 47
 48    fn to_bytes_strict<CS: ConstraintSystem<P::Fp>>(
 49        &self,
 50        cs: CS,
 51    ) -> Result<Vec<UInt8>, SynthesisError> {
 52        self.to_bytes(cs)
 53    }
 54}
 55
 56type Fp2G<P> = Fp2Gadget<<P as Bls12Parameters>::Fp2Params, <P as Bls12Parameters>::Fp>;
 57type LCoeff<P> = (Fp2G<P>, Fp2G<P>);
 58#[derive(Derivative)]
 59#[derivative(
 60    Clone(bound = "Fp2Gadget<P::Fp2Params, P::Fp>: Clone"),
 61    Debug(bound = "Fp2Gadget<P::Fp2Params, P::Fp>: Debug")
 62)]
 63pub struct G2PreparedGadget<P: Bls12Parameters> {
 64    pub ell_coeffs: Vec<LCoeff<P>>,
 65}
 66
 67impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
 68    #[inline]
 69    fn to_bytes<CS: ConstraintSystem<P::Fp>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
 70        let mut bytes = Vec::new();
 71        for (i, coeffs) in self.ell_coeffs.iter().enumerate() {
 72            let mut cs = cs.ns(|| format!("Iteration {}", i));
 73            bytes.extend_from_slice(&coeffs.0.to_bytes(&mut cs.ns(|| "c0"))?);
 74            bytes.extend_from_slice(&coeffs.1.to_bytes(&mut cs.ns(|| "c1"))?);
 75        }
 76        Ok(bytes)
 77    }
 78
 79    fn to_bytes_strict<CS: ConstraintSystem<P::Fp>>(
 80        &self,
 81        cs: CS,
 82    ) -> Result<Vec<UInt8>, SynthesisError> {
 83        self.to_bytes(cs)
 84    }
 85}
 86
 87impl<P: Bls12Parameters> G2PreparedGadget<P> {
 88    pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
 89        mut cs: CS,
 90        q: &G2Gadget<P>,
 91    ) -> Result<Self, SynthesisError> {
 92        let two_inv = P::Fp::one().double().inverse().unwrap();
 93        let zero = G2Gadget::<P>::zero(cs.ns(|| "zero"))?;
 94        q.enforce_not_equal(cs.ns(|| "enforce not zero"), &zero)?;
 95        let mut ell_coeffs = vec![];
 96        let mut r = q.clone();
 97
 98        for (j, i) in BitIterator::new(P::X).skip(1).enumerate() {
 99            let mut cs = cs.ns(|| format!("Iteration {}", j));
100            ell_coeffs.push(Self::double(cs.ns(|| "double"), &mut r, &two_inv)?);
101
102            if i {
103                ell_coeffs.push(Self::add(cs.ns(|| "add"), &mut r, &q)?);
104            }
105        }
106
107        Ok(Self { ell_coeffs })
108    }
109
110    fn double<CS: ConstraintSystem<P::Fp>>(
111        mut cs: CS,
112        r: &mut G2Gadget<P>,
113        two_inv: &P::Fp,
114    ) -> Result<LCoeff<P>, SynthesisError> {
115        let a = r.y.inverse(cs.ns(|| "Inverse"))?;
116        let mut b = r.x.square(cs.ns(|| "square x"))?;
117        let b_tmp = b.clone();
118        b.mul_by_fp_constant_in_place(cs.ns(|| "mul by two_inv"), two_inv)?;
119        b.add_in_place(cs.ns(|| "compute b"), &b_tmp)?;
120
121        let c = a.mul(cs.ns(|| "compute c"), &b)?;
122        let d = r.x.double(cs.ns(|| "compute d"))?;
123        let x3 = c.square(cs.ns(|| "c^2"))?.sub(cs.ns(|| "sub d"), &d)?;
124        let e = c
125            .mul(cs.ns(|| "c*r.x"), &r.x)?
126            .sub(cs.ns(|| "sub r.y"), &r.y)?;
127        let c_x3 = c.mul(cs.ns(|| "c*x_3"), &x3)?;
128        let y3 = e.sub(cs.ns(|| "e = c * x3"), &c_x3)?;
129        let mut f = c;
130        f.negate_in_place(cs.ns(|| "c = -c"))?;
131        r.x = x3;
132        r.y = y3;
133        match P::TWIST_TYPE {
134            TwistType::M => Ok((e, f)),
135            TwistType::D => Ok((f, e)),
136        }
137    }
138
139    fn add<CS: ConstraintSystem<P::Fp>>(
140        mut cs: CS,
141        r: &mut G2Gadget<P>,
142        q: &G2Gadget<P>,
143    ) -> Result<LCoeff<P>, SynthesisError> {
144        let a =
145            q.x.sub(cs.ns(|| "q.x - r.x"), &r.x)?
146                .inverse(cs.ns(|| "calc a"))?;
147        let b = q.y.sub(cs.ns(|| "q.y - r.y"), &r.y)?;
148        let c = a.mul(cs.ns(|| "compute c"), &b)?;
149        let d = r.x.add(cs.ns(|| "r.x + q.x"), &q.x)?;
150        let x3 = c.square(cs.ns(|| "c^2"))?.sub(cs.ns(|| "sub d"), &d)?;
151
152        let e =
153            r.x.sub(cs.ns(|| "r.x - x3"), &x3)?
154                .mul(cs.ns(|| "c * (r.x - x3)"), &c)?;
155        let y3 = e.sub(cs.ns(|| "calc y3"), &r.y)?;
156        let g = c
157            .mul(cs.ns(|| "c*r.x"), &r.x)?
158            .sub(cs.ns(|| "calc g"), &r.y)?;
159        let mut f = c;
160        f.negate_in_place(cs.ns(|| "c = -c"))?;
161        r.x = x3;
162        r.y = y3;
163        match P::TWIST_TYPE {
164            TwistType::M => Ok((g, f)),
165            TwistType::D => Ok((f, g)),
166        }
167    }
168}