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, G2Prepared, 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::{borrow::Borrow, fmt::Debug, ops::Mul};
 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> AllocGadget<G1Prepared<P>, P::Fp> for G1PreparedGadget<P> {
 34    fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
 35        mut cs: CS,
 36        t: T,
 37    ) -> Result<Self, SynthesisError>
 38    where
 39        T: Borrow<G1Prepared<P>>,
 40    {
 41        let obj = t.borrow();
 42
 43        Ok(Self(G1Gadget::<P>::alloc_constant(
 44            &mut cs.ns(|| "g1"),
 45            &obj.0.into(),
 46        )?))
 47    }
 48
 49    fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
 50    where
 51        F: FnOnce() -> Result<T, SynthesisError>,
 52        T: Borrow<G1Prepared<P>>,
 53    {
 54        todo!()
 55    }
 56
 57    fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
 58        _cs: CS,
 59        _f: F,
 60    ) -> Result<Self, SynthesisError>
 61    where
 62        F: FnOnce() -> Result<T, SynthesisError>,
 63        T: Borrow<G1Prepared<P>>,
 64    {
 65        todo!()
 66    }
 67}
 68
 69impl<P: Bls12Parameters> G1PreparedGadget<P> {
 70    pub fn get_value(&self) -> Option<G1Prepared<P>> {
 71        Some(G1Prepared::from(self.0.get_value().unwrap().into_affine()))
 72    }
 73
 74    pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
 75        _cs: CS,
 76        q: &G1Gadget<P>,
 77    ) -> Result<Self, SynthesisError> {
 78        Ok(G1PreparedGadget(q.clone()))
 79    }
 80}
 81
 82impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
 83    #[inline]
 84    fn to_bytes<CS: ConstraintSystem<P::Fp>>(
 85        &self,
 86        mut cs: CS,
 87    ) -> Result<Vec<UInt8>, SynthesisError> {
 88        self.0.to_bytes(&mut cs.ns(|| "g_alpha to bytes"))
 89    }
 90
 91    fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
 92        &self,
 93        mut cs: CS,
 94    ) -> Result<Vec<UInt8>, SynthesisError> {
 95        self.0
 96            .to_non_unique_bytes(&mut cs.ns(|| "g_alpha to bytes"))
 97    }
 98}
 99
100type Fp2G<P> = Fp2Gadget<<P as Bls12Parameters>::Fp2Params, <P as Bls12Parameters>::Fp>;
101type LCoeff<P> = (Fp2G<P>, Fp2G<P>);
102#[derive(Derivative)]
103#[derivative(
104    Clone(bound = "Fp2Gadget<P::Fp2Params, P::Fp>: Clone"),
105    Debug(bound = "Fp2Gadget<P::Fp2Params, P::Fp>: Debug")
106)]
107pub struct G2PreparedGadget<P: Bls12Parameters> {
108    pub ell_coeffs: Vec<LCoeff<P>>,
109}
110
111impl<P: Bls12Parameters> AllocGadget<G2Prepared<P>, P::Fp> for G2PreparedGadget<P> {
112    fn alloc_constant<T, CS: ConstraintSystem<P::Fp>>(
113        mut cs: CS,
114        t: T,
115    ) -> Result<Self, SynthesisError>
116    where
117        T: Borrow<G2Prepared<P>>,
118    {
119        let obj = t.borrow();
120        let mut res = Vec::<LCoeff<P>>::new();
121
122        for (i, (x, y, z)) in obj.ell_coeffs.iter().enumerate() {
123            let z_inverse = z.inverse().unwrap();
124
125            let x_normalized = x.mul(&z_inverse);
126            let y_normalized = y.mul(&z_inverse);
127
128            let x_gadget =
129                Fp2Gadget::alloc_constant(&mut cs.ns(|| format!("alloc_x#{}", i)), x_normalized)?;
130            let y_gadget =
131                Fp2Gadget::alloc_constant(&mut cs.ns(|| format!("alloc_y#{}", i)), y_normalized)?;
132
133            res.push((x_gadget, y_gadget));
134        }
135
136        Ok(Self { ell_coeffs: res })
137    }
138
139    fn alloc<F, T, CS: ConstraintSystem<P::Fp>>(_cs: CS, _f: F) -> Result<Self, SynthesisError>
140    where
141        F: FnOnce() -> Result<T, SynthesisError>,
142        T: Borrow<G2Prepared<P>>,
143    {
144        todo!()
145    }
146
147    fn alloc_input<F, T, CS: ConstraintSystem<P::Fp>>(
148        _cs: CS,
149        _f: F,
150    ) -> Result<Self, SynthesisError>
151    where
152        F: FnOnce() -> Result<T, SynthesisError>,
153        T: Borrow<G2Prepared<P>>,
154    {
155        todo!()
156    }
157}
158
159impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
160    #[inline]
161    fn to_bytes<CS: ConstraintSystem<P::Fp>>(
162        &self,
163        mut cs: CS,
164    ) -> Result<Vec<UInt8>, SynthesisError> {
165        let mut bytes = Vec::new();
166        for (i, coeffs) in self.ell_coeffs.iter().enumerate() {
167            let mut cs = cs.ns(|| format!("Iteration {}", i));
168            bytes.extend_from_slice(&coeffs.0.to_bytes(&mut cs.ns(|| "c0"))?);
169            bytes.extend_from_slice(&coeffs.1.to_bytes(&mut cs.ns(|| "c1"))?);
170        }
171        Ok(bytes)
172    }
173
174    fn to_non_unique_bytes<CS: ConstraintSystem<P::Fp>>(
175        &self,
176        mut cs: CS,
177    ) -> Result<Vec<UInt8>, SynthesisError> {
178        let mut bytes = Vec::new();
179        for (i, coeffs) in self.ell_coeffs.iter().enumerate() {
180            let mut cs = cs.ns(|| format!("Iteration {}", i));
181            bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes(&mut cs.ns(|| "c0"))?);
182            bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes(&mut cs.ns(|| "c1"))?);
183        }
184        Ok(bytes)
185    }
186}
187
188impl<P: Bls12Parameters> G2PreparedGadget<P> {
189    pub fn from_affine<CS: ConstraintSystem<P::Fp>>(
190        mut cs: CS,
191        q: &G2Gadget<P>,
192    ) -> Result<Self, SynthesisError> {
193        let two_inv = P::Fp::one().double().inverse().unwrap();
194        let zero = G2Gadget::<P>::zero(cs.ns(|| "zero"))?;
195        q.enforce_not_equal(cs.ns(|| "enforce not zero"), &zero)?;
196        let mut ell_coeffs = vec![];
197        let mut r = q.clone();
198
199        for (j, i) in BitIterator::new(P::X).skip(1).enumerate() {
200            let mut cs = cs.ns(|| format!("Iteration {}", j));
201            ell_coeffs.push(Self::double(cs.ns(|| "double"), &mut r, &two_inv)?);
202
203            if i {
204                ell_coeffs.push(Self::add(cs.ns(|| "add"), &mut r, &q)?);
205            }
206        }
207
208        Ok(Self { ell_coeffs })
209    }
210
211    fn double<CS: ConstraintSystem<P::Fp>>(
212        mut cs: CS,
213        r: &mut G2Gadget<P>,
214        two_inv: &P::Fp,
215    ) -> Result<LCoeff<P>, SynthesisError> {
216        let a = r.y.inverse(cs.ns(|| "Inverse"))?;
217        let mut b = r.x.square(cs.ns(|| "square x"))?;
218        let b_tmp = b.clone();
219        b.mul_by_fp_constant_in_place(cs.ns(|| "mul by two_inv"), two_inv)?;
220        b.add_in_place(cs.ns(|| "compute b"), &b_tmp)?;
221
222        let c = a.mul(cs.ns(|| "compute c"), &b)?;
223        let d = r.x.double(cs.ns(|| "compute d"))?;
224        let x3 = c.square(cs.ns(|| "c^2"))?.sub(cs.ns(|| "sub d"), &d)?;
225        let e = c
226            .mul(cs.ns(|| "c*r.x"), &r.x)?
227            .sub(cs.ns(|| "sub r.y"), &r.y)?;
228        let c_x3 = c.mul(cs.ns(|| "c*x_3"), &x3)?;
229        let y3 = e.sub(cs.ns(|| "e = c * x3"), &c_x3)?;
230        let mut f = c;
231        f.negate_in_place(cs.ns(|| "c = -c"))?;
232        r.x = x3;
233        r.y = y3;
234        match P::TWIST_TYPE {
235            TwistType::M => Ok((e, f)),
236            TwistType::D => Ok((f, e)),
237        }
238    }
239
240    fn add<CS: ConstraintSystem<P::Fp>>(
241        mut cs: CS,
242        r: &mut G2Gadget<P>,
243        q: &G2Gadget<P>,
244    ) -> Result<LCoeff<P>, SynthesisError> {
245        let a =
246            q.x.sub(cs.ns(|| "q.x - r.x"), &r.x)?
247                .inverse(cs.ns(|| "calc a"))?;
248        let b = q.y.sub(cs.ns(|| "q.y - r.y"), &r.y)?;
249        let c = a.mul(cs.ns(|| "compute c"), &b)?;
250        let d = r.x.add(cs.ns(|| "r.x + q.x"), &q.x)?;
251        let x3 = c.square(cs.ns(|| "c^2"))?.sub(cs.ns(|| "sub d"), &d)?;
252
253        let e =
254            r.x.sub(cs.ns(|| "r.x - x3"), &x3)?
255                .mul(cs.ns(|| "c * (r.x - x3)"), &c)?;
256        let y3 = e.sub(cs.ns(|| "calc y3"), &r.y)?;
257        let g = c
258            .mul(cs.ns(|| "c*r.x"), &r.x)?
259            .sub(cs.ns(|| "calc g"), &r.y)?;
260        let mut f = c;
261        f.negate_in_place(cs.ns(|| "c = -c"))?;
262        r.x = x3;
263        r.y = y3;
264        match P::TWIST_TYPE {
265            TwistType::M => Ok((g, f)),
266            TwistType::D => Ok((f, g)),
267        }
268    }
269}