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 BitIteratorBE, 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 BitIteratorBE::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}