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