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}