halo2curves/derive/
pairing.rs
1#[macro_export]
2macro_rules! impl_miller_loop_components {
3 (
4 $engine:ident,
5 $g1:ident,
6 $g1affine:ident,
7 $g2:ident,
8 $g2affine:ident,
9 $base:ident,
10 $target:ident,
11 $scalar:ident
12 ) => {
13 #[derive(Clone, Debug)]
14 pub struct $engine;
15
16 impl Engine for $engine {
17 type Fr = $scalar;
18 type G1 = $g1;
19 type G1Affine = $g1affine;
20 type G2 = $g2;
21 type G2Affine = $g2affine;
22 type Gt = Gt;
23
24 fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
25 $engine::multi_miller_loop(&[(p, q)]).final_exponentiation()
26 }
27 }
28
29 impl MultiMillerLoop for $engine {
30 type G2Prepared = $g2affine;
31 type Result = $base;
32
33 fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
34 multi_miller_loop(terms)
35 }
36 }
37
38 impl PairingCurveAffine for $g1affine {
39 type Pair = $g2affine;
40 type PairingResult = $target;
41
42 fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
43 $engine::pairing(&self, &other)
44 }
45 }
46
47 impl PairingCurveAffine for $g2affine {
48 type Pair = $g1affine;
49 type PairingResult = $target;
50
51 fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
52 $engine::pairing(&other, &self)
53 }
54 }
55
56 fn double(f: &mut $base, r: &mut $g2, p: &$g1affine) {
57 use ff::Field;
58 let t0 = r.x.square();
59 let t1 = r.y.square();
60 let t2 = t1.square();
61 let t3 = (t1 + r.x).square() - t0 - t2;
62 let t3 = t3 + t3;
63 let t4 = t0 + t0 + t0;
64 let t6 = r.x + t4;
65 let t5 = t4.square();
66 let zsquared = r.z.square();
67 r.x = t5 - t3 - t3;
68 r.z = (r.z + r.y).square() - t1 - zsquared;
69 r.y = (t3 - r.x) * t4;
70 let t2 = t2 + t2;
71 let t2 = t2 + t2;
72 let t2 = t2 + t2;
73 r.y -= t2;
74 let t3 = t4 * zsquared;
75 let t3 = t3 + t3;
76 let t3 = -t3;
77 let t6 = t6.square() - t0 - t5;
78 let t1 = t1 + t1;
79 let t1 = t1 + t1;
80 let t6 = t6 - t1;
81 let t0 = r.z * zsquared;
82 let t0 = t0 + t0;
83
84 ell(f, &(t0, t3, t6), p);
85 }
86
87 fn add(f: &mut $base, r: &mut $g2, q: &$g2affine, p: &$g1affine) {
88 use ff::Field;
89 let zsquared = r.z.square();
90 let ysquared = q.y.square();
91 let t0 = zsquared * q.x;
92 let t1 = ((q.y + r.z).square() - ysquared - zsquared) * zsquared;
93 let t2 = t0 - r.x;
94 let t3 = t2.square();
95 let t4 = t3 + t3;
96 let t4 = t4 + t4;
97 let t5 = t4 * t2;
98 let t6 = t1 - r.y - r.y;
99 let t9 = t6 * q.x;
100 let t7 = t4 * r.x;
101 r.x = t6.square() - t5 - t7 - t7;
102 r.z = (r.z + t2).square() - zsquared - t3;
103 let t10 = q.y + r.z;
104 let t8 = (t7 - r.x) * t6;
105 let t0 = r.y * t5;
106 let t0 = t0 + t0;
107 r.y = t8 - t0;
108 let t10 = t10.square() - ysquared;
109 let ztsquared = r.z.square();
110 let t10 = t10 - ztsquared;
111 let t9 = t9 + t9 - t10;
112 let t10 = r.z + r.z;
113 let t6 = -t6;
114 let t1 = t6 + t6;
115
116 ell(f, &(t10, t1, t9), p);
117 }
118 };
119}
120
121#[macro_export]
122macro_rules! impl_gt {
123 (
124 $target:ident,
125 $base:ident,
126 $scalar:ident
127 ) => {
128 #[derive(Copy, Clone, Debug, Default)]
129 pub struct $target(pub(crate) $base);
130
131 impl ConstantTimeEq for $target {
132 fn ct_eq(&self, other: &Self) -> Choice {
133 self.0.ct_eq(&other.0)
134 }
135 }
136
137 impl ConditionallySelectable for $target {
138 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
139 $target($base::conditional_select(&a.0, &b.0, choice))
140 }
141 }
142
143 impl Eq for $target {}
144 impl PartialEq for $target {
145 #[inline]
146 fn eq(&self, other: &Self) -> bool {
147 bool::from(self.ct_eq(other))
148 }
149 }
150
151 impl $target {
152 pub fn identity() -> $target {
154 $target($base::one())
155 }
156
157 pub fn double(&self) -> $target {
159 use ff::Field;
160 $target(self.0.square())
161 }
162 }
163
164 impl<'a> Neg for &'a $target {
165 type Output = $target;
166
167 #[inline]
168 fn neg(self) -> $target {
169 let mut u = self.0;
171 u.conjugate();
172 $target(u)
173 }
174 }
175
176 impl Neg for $target {
177 type Output = $target;
178
179 #[inline]
180 fn neg(self) -> $target {
181 -&self
182 }
183 }
184
185 impl<'a, 'b> Add<&'b $target> for &'a $target {
186 type Output = $target;
187
188 #[inline]
189 #[allow(clippy::suspicious_arithmetic_impl)]
190 fn add(self, rhs: &'b $target) -> $target {
191 $target(self.0 * rhs.0)
192 }
193 }
194
195 impl<'a, 'b> Sub<&'b $target> for &'a $target {
196 type Output = $target;
197
198 #[inline]
199 fn sub(self, rhs: &'b $target) -> $target {
200 self + (-rhs)
201 }
202 }
203
204 #[allow(clippy::suspicious_arithmetic_impl)]
205 impl<'a, 'b> Mul<&'b $scalar> for &'a $target {
206 type Output = $target;
207
208 fn mul(self, other: &'b $scalar) -> Self::Output {
209 let mut acc = $target::identity();
210
211 for bit in other
212 .to_repr()
213 .as_ref()
214 .iter()
215 .rev()
216 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
217 .skip(1)
218 {
219 acc = acc.double();
220 acc = $target::conditional_select(&acc, &(acc + self), bit);
221 }
222
223 acc
224 }
225 }
226
227 $crate::impl_binops_additive!($target, $target);
228 $crate::impl_binops_multiplicative!($target, $scalar);
229
230 impl<T> Sum<T> for $target
231 where
232 T: Borrow<$target>,
233 {
234 fn sum<I>(iter: I) -> Self
235 where
236 I: Iterator<Item = T>,
237 {
238 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
239 }
240 }
241
242 impl Group for $target {
243 type Scalar = $scalar;
244
245 fn random(rng: impl RngCore) -> Self {
246 use ff::Field;
247 $base::random(rng).final_exponentiation()
248 }
249
250 fn identity() -> Self {
251 Self::identity()
252 }
253
254 fn generator() -> Self {
255 unimplemented!()
256 }
257
258 fn is_identity(&self) -> Choice {
259 self.ct_eq(&Self::identity())
260 }
261
262 #[must_use]
263 fn double(&self) -> Self {
264 self.double()
265 }
266 }
267 };
268}