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::{
  3        bls12::{Bls12Parameters, G1Prepared, G2Prepared, TwistType},
  4        short_weierstrass_jacobian::GroupAffine,
  5    },
  6    fields::Field,
  7    BitIterator, One,
  8};
  9use r1cs_core::SynthesisError;
 10
 11use crate::{
 12    fields::{fp::FpVar, fp2::Fp2Var, FieldVar},
 13    groups::curves::short_weierstrass::*,
 14    Vec,
 15};
 16
 17use core::fmt::Debug;
 18
 19pub type G1Var<P> =
 20    ProjectiveVar<<P as Bls12Parameters>::G1Parameters, FpVar<<P as Bls12Parameters>::Fp>>;
 21pub type G1AffineVar<P> =
 22    AffineVar<<P as Bls12Parameters>::G1Parameters, FpVar<<P as Bls12Parameters>::Fp>>;
 23
 24pub type G2Var<P> = ProjectiveVar<<P as Bls12Parameters>::G2Parameters, Fp2G<P>>;
 25pub type G2AffineVar<P> = AffineVar<<P as Bls12Parameters>::G2Parameters, Fp2G<P>>;
 26
 27#[derive(Derivative)]
 28#[derivative(Clone(bound = "G1Var<P>: Clone"), Debug(bound = "G1Var<P>: Debug"))]
 29pub struct G1PreparedVar<P: Bls12Parameters>(pub AffineVar<P::G1Parameters, FpVar<P::Fp>>);
 30
 31impl<P: Bls12Parameters> G1PreparedVar<P> {
 32    pub fn value(&self) -> Result<G1Prepared<P>, SynthesisError> {
 33        let x = self.0.x.value()?;
 34        let y = self.0.y.value()?;
 35        let infinity = self.0.infinity.value()?;
 36        let g = GroupAffine::new(x, y, infinity);
 37        Ok(g.into())
 38    }
 39
 40    pub fn from_group_var(q: &G1Var<P>) -> Result<Self, SynthesisError> {
 41        let g = q.to_affine()?;
 42        Ok(Self(g))
 43    }
 44}
 45
 46impl<P: Bls12Parameters> AllocVar<G1Prepared<P>, P::Fp> for G1PreparedVar<P> {
 47    fn new_variable<T: Borrow<G1Prepared<P>>>(
 48        cs: impl Into<Namespace<P::Fp>>,
 49        f: impl FnOnce() -> Result<T, SynthesisError>,
 50        mode: AllocationMode,
 51    ) -> Result<Self, SynthesisError> {
 52        let ns = cs.into();
 53        let cs = ns.cs();
 54        let g1_prep = f().map(|b| b.borrow().0);
 55
 56        let x = FpVar::new_variable(cs.ns("x"), || g1_prep.map(|g| g.x), mode)?;
 57        let y = FpVar::new_variable(cs.ns("y"), || g1_prep.map(|g| g.y), mode)?;
 58        let infinity = Boolean::new_variable(cs.ns("inf"), || g1_prep.map(|g| g.infinity), mode)?;
 59        let g = AffineVar::new(x, y, infinity);
 60        Ok(Self(g))
 61    }
 62}
 63
 64impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
 65    #[inline]
 66    fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
 67        let mut bytes = self.0.x.to_bytes()?;
 68        let y_bytes = self.0.y.to_bytes()?;
 69        let inf_bytes = self.0.infinity.to_bytes()?;
 70        bytes.extend_from_slice(&y_bytes);
 71        bytes.extend_from_slice(&inf_bytes);
 72        Ok(bytes)
 73    }
 74
 75    fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
 76        let mut bytes = self.0.x.to_bytes()?;
 77        let y_bytes = self.0.y.to_bytes()?;
 78        let inf_bytes = self.0.infinity.to_bytes()?;
 79        bytes.extend_from_slice(&y_bytes);
 80        bytes.extend_from_slice(&inf_bytes);
 81        Ok(bytes)
 82    }
 83}
 84
 85type Fp2G<P> = Fp2Var<<P as Bls12Parameters>::Fp2Params>;
 86type LCoeff<P> = (Fp2G<P>, Fp2G<P>);
 87#[derive(Derivative)]
 88#[derivative(
 89    Clone(bound = "Fp2Var<P::Fp2Params>: Clone"),
 90    Debug(bound = "Fp2Var<P::Fp2Params>: Debug")
 91)]
 92pub struct G2PreparedVar<P: Bls12Parameters> {
 93    pub ell_coeffs: Vec<LCoeff<P>>,
 94}
 95
 96impl<P: Bls12Parameters> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
 97    fn new_variable<T: Borrow<G2Prepared<P>>>(
 98        cs: impl Into<Namespace<P::Fp>>,
 99        f: impl FnOnce() -> Result<T, SynthesisError>,
100        mode: AllocationMode,
101    ) -> Result<Self, SynthesisError> {
102        let ns = cs.into();
103        let cs = ns.cs();
104        let g2_prep = f().map(|b| {
105            let projective_coeffs = &b.borrow().ell_coeffs;
106            let mut z_s = projective_coeffs
107                .iter()
108                .map(|(_, _, z)| *z)
109                .collect::<Vec<_>>();
110            algebra::fields::batch_inversion(&mut z_s);
111            projective_coeffs
112                .iter()
113                .zip(z_s)
114                .map(|((x, y, _), z_inv)| (*x * &z_inv, *y * &z_inv))
115                .collect::<Vec<_>>()
116        });
117
118        let l = Vec::new_variable(
119            cs.ns("l"),
120            || {
121                g2_prep
122                    .clone()
123                    .map(|c| c.iter().map(|(l, _)| *l).collect::<Vec<_>>())
124            },
125            mode,
126        )?;
127        let r = Vec::new_variable(
128            cs.ns("r"),
129            || g2_prep.map(|c| c.iter().map(|(_, r)| *r).collect::<Vec<_>>()),
130            mode,
131        )?;
132        let ell_coeffs = l.into_iter().zip(r).collect();
133        Ok(Self { ell_coeffs })
134    }
135}
136
137impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
138    #[inline]
139    fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
140        let mut bytes = Vec::new();
141        for coeffs in &self.ell_coeffs {
142            bytes.extend_from_slice(&coeffs.0.to_bytes()?);
143            bytes.extend_from_slice(&coeffs.1.to_bytes()?);
144        }
145        Ok(bytes)
146    }
147
148    fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
149        let mut bytes = Vec::new();
150        for coeffs in &self.ell_coeffs {
151            bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes()?);
152            bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes()?);
153        }
154        Ok(bytes)
155    }
156}
157
158impl<P: Bls12Parameters> G2PreparedVar<P> {
159    pub fn from_group_var(q: &G2Var<P>) -> Result<Self, SynthesisError> {
160        let q = q.to_affine()?;
161        let two_inv = P::Fp::one().double().inverse().unwrap();
162        // Enforce that `q` is not the point at infinity.
163        q.infinity.enforce_not_equal(&Boolean::Constant(true))?;
164        let mut ell_coeffs = vec![];
165        let mut r = q.clone();
166
167        for i in BitIterator::new(P::X).skip(1) {
168            ell_coeffs.push(Self::double(&mut r, &two_inv)?);
169
170            if i {
171                ell_coeffs.push(Self::add(&mut r, &q)?);
172            }
173        }
174
175        Ok(Self { ell_coeffs })
176    }
177
178    fn double(r: &mut G2AffineVar<P>, two_inv: &P::Fp) -> Result<LCoeff<P>, SynthesisError> {
179        let a = r.y.inverse()?;
180        let mut b = r.x.square()?;
181        let b_tmp = b.clone();
182        b.mul_assign_by_base_field_constant(*two_inv);
183        b += &b_tmp;
184
185        let c = &a * &b;
186        let d = r.x.double()?;
187        let x3 = c.square()? - &d;
188        let e = &c * &r.x - &r.y;
189        let c_x3 = &c * &x3;
190        let y3 = &e - &c_x3;
191        let mut f = c;
192        f.negate_in_place()?;
193        r.x = x3;
194        r.y = y3;
195        match P::TWIST_TYPE {
196            TwistType::M => Ok((e, f)),
197            TwistType::D => Ok((f, e)),
198        }
199    }
200
201    fn add(r: &mut G2AffineVar<P>, q: &G2AffineVar<P>) -> Result<LCoeff<P>, SynthesisError> {
202        let a = (&q.x - &r.x).inverse()?;
203        let b = &q.y - &r.y;
204        let c = &a * &b;
205        let d = &r.x + &q.x;
206        let x3 = c.square()? - &d;
207
208        let e = (&r.x - &x3) * &c;
209        let y3 = e - &r.y;
210        let g = &c * &r.x - &r.y;
211        let mut f = c;
212        f.negate_in_place()?;
213        r.x = x3;
214        r.y = y3;
215        match P::TWIST_TYPE {
216            TwistType::M => Ok((g, f)),
217            TwistType::D => Ok((f, g)),
218        }
219    }
220}