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            /// Returns the group identity, which is $1$.
153            pub fn identity() -> $target {
154                $target($base::one())
155            }
156
157            /// Doubles this group element.
158            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                // The element is unitary, so we just conjugate.
170                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}