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