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