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