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