Skip to content

Commit d941b5e

Browse files
clintfredcoltfred
authored andcommitted
Performance improvements and cleanups (#55)
1 parent 1c01789 commit d941b5e

File tree

5 files changed

+91
-91
lines changed

5 files changed

+91
-91
lines changed

src/internal/field.rs

Lines changed: 32 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,6 @@ pub trait ExtensionField: Field
126126
where
127127
Self: Sized + From<u8>,
128128
{
129-
/// Xi is u + 3 which is v^3.
130-
/// v^p == Xi^((p-1)/3) * v
131-
fn xi() -> Fp2Elem<Self> {
132-
Fp2Elem {
133-
elem1: Self::one(),
134-
elem2: Self::from(3u8),
135-
}
136-
}
137129
///Precomputed xi.inv() * 9
138130
fn xi_inv_times_9() -> Fp2Elem<Self>;
139131

@@ -151,29 +143,24 @@ where
151143

152144
///v is the thing that cubes to xi
153145
///v^3 = u+3, because by definition it is a solution to the equation y^3 - (u + 3)
146+
#[inline]
154147
fn v() -> Fp6Elem<Self> {
155148
Fp6Elem {
156149
elem1: Zero::zero(),
157150
elem2: One::one(),
158151
elem3: Zero::zero(),
159152
}
160153
}
154+
155+
/// 3 / (u+3)
156+
/// pre-calculate as an optimization
157+
/// ExtensionField::xi().inv() * 3;
158+
fn twisted_curve_const_coeff() -> Fp2Elem<Self>;
161159
}
162160

163161
impl ExtensionField for fp_256::Monty {
164-
fn xi() -> Fp2Elem<Self> {
165-
Fp2Elem {
166-
elem1: fp_256::Monty::new([
167-
1368961080, 1174866893, 1632604085, 2004383869, 1511972380, 1964912876, 1176826515,
168-
403865604, 70,
169-
]),
170-
elem2: fp_256::Monty::new([
171-
381778497, 559663760, 555210920, 1938629360, 1980684343, 291306425, 697096529,
172-
1840680552, 66,
173-
]),
174-
}
175-
}
176162
//precalculate this since it's used in every double and add operation in the extension field.
163+
//xi is u + 3 or Fp2Elem(1, 3)
177164
// Fp256::xi().inv() * 9
178165
fn xi_inv_times_9() -> Fp2Elem<Self> {
179166
Fp2Elem {
@@ -236,39 +223,24 @@ impl ExtensionField for fp_256::Monty {
236223
}
237224
}
238225

239-
///v is the thing that cubes to xi
240-
///v^3 = u+3, because by definition it is a solution to the equation y^3 - (u + 3)
241-
fn v() -> Fp6Elem<Self> {
242-
Fp6Elem {
243-
elem1: Zero::zero(),
244-
elem2: Fp2Elem {
245-
elem1: Zero::zero(),
246-
elem2: fp_256::Monty::new([
247-
1368961080, 1174866893, 1632604085, 2004383869, 1511972380, 1964912876,
248-
1176826515, 403865604, 70,
249-
]),
250-
},
251-
elem3: Zero::zero(),
252-
}
253-
}
254-
}
255-
256-
impl ExtensionField for fp_480::Monty {
257-
fn xi() -> Fp2Elem<Self> {
226+
#[inline]
227+
fn twisted_curve_const_coeff() -> Fp2Elem<Self> {
258228
Fp2Elem {
259-
elem1: fp_480::Monty::new([
260-
1588384315, 657481659, 1879608514, 2019977405, 241404753, 1339062904, 639566708,
261-
740072562, 1004131918, 1560224833, 2014075, 1848411426, 1733309265, 1811487384,
262-
799788540, 19667,
229+
elem1: fp_256::Monty::new([
230+
1925150376, 516250914, 1051564560, 1369812449, 731601065, 672046428, 625168271,
231+
1952553705, 93,
263232
]),
264-
elem2: fp_480::Monty::new([
265-
1562186266, 585547362, 445363961, 373107586, 235669429, 70320378, 1725584133,
266-
1655137918, 674554062, 1273113365, 570248622, 1027777883, 144574781, 808941279,
267-
1969907309, 26235,
233+
elem2: fp_256::Monty::new([
234+
1674758358, 86153800, 1235541696, 1892123501, 768178752, 600790531, 1643777575,
235+
1474105998, 5,
268236
]),
269237
}
270238
}
239+
}
240+
241+
impl ExtensionField for fp_480::Monty {
271242
// precalculate this since it's used in every double and add operation in the extension field.
243+
// xi is u + 3 or Fp2Elem(1, 3)
272244
// Fp480::xi().inv() * 9
273245
fn xi_inv_times_9() -> Fp2Elem<Self> {
274246
Fp2Elem {
@@ -335,21 +307,19 @@ impl ExtensionField for fp_480::Monty {
335307
}
336308
}
337309

338-
///v is the thing that cubes to xi
339-
///v^3 = u+3, because by definition it is a solution to the equation y^3 - (u + 3)
340-
fn v() -> Fp6Elem<Self> {
341-
Fp6Elem {
342-
elem1: Zero::zero(),
343-
elem2: Fp2Elem {
344-
elem1: Zero::zero(),
345-
//This is 1 in monty form
346-
elem2: fp_480::Monty::new([
347-
1588384315, 657481659, 1879608514, 2019977405, 241404753, 1339062904,
348-
639566708, 740072562, 1004131918, 1560224833, 2014075, 1848411426, 1733309265,
349-
1811487384, 799788540, 19667,
350-
]),
351-
},
352-
elem3: Zero::zero(),
310+
#[inline]
311+
fn twisted_curve_const_coeff() -> Fp2Elem<Self> {
312+
Fp2Elem {
313+
elem1: fp_480::Monty::new([
314+
1976657987, 2124705180, 1103755761, 1290923474, 2085255841, 1647224075, 1270424569,
315+
286550022, 1158572853, 451253923, 1853842034, 2007948773, 1667592921, 2116284018,
316+
790821013, 23589,
317+
]),
318+
elem2: fp_480::Monty::new([
319+
1531442428, 2081544602, 1531699218, 302801582, 1652317917, 456481830, 1063041565,
320+
835589236, 1390322869, 278987042, 1335789303, 1086071918, 1573345690, 1085259625,
321+
1063395545, 27530,
322+
]),
353323
}
354324
}
355325
}

src/internal/fp2elem.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,41 @@ pub struct Fp2Elem<T> {
2525
pub elem2: T,
2626
}
2727

28+
/// Xi is u + 3 which is v^3.
29+
/// v^p == Xi^((p-1)/3) * v
30+
/// This is an empty type which allows for Fp2 * Xi in order to multiply the fp2 element * Fp2(1, 3).
31+
pub struct Xi;
32+
33+
impl<T> Mul<Fp2Elem<T>> for Xi
34+
where
35+
T: Mul<u32, Output = T> + Sub<Output = T> + Add<Output = T> + Copy,
36+
{
37+
type Output = Fp2Elem<T>;
38+
#[inline]
39+
fn mul(self, fp2: Fp2Elem<T>) -> Fp2Elem<T> {
40+
fp2 * self
41+
}
42+
}
43+
44+
impl<T> Mul<Xi> for Fp2Elem<T>
45+
where
46+
T: Mul<u32, Output = T> + Sub<Output = T> + Add<Output = T> + Copy,
47+
{
48+
type Output = Fp2Elem<T>;
49+
///This is a shorthand for multiplying times u + 3.
50+
/// (a*u+b)*(u+3) = -a+3b + u*(3a+b)
51+
/// In this case we expand out the additions.
52+
#[inline]
53+
fn mul(self, _xi: Xi) -> Self {
54+
Fp2Elem {
55+
//3a+b
56+
elem1: self.elem1 + self.elem1 + self.elem1 + self.elem2,
57+
//-a+3b
58+
elem2: self.elem2 + self.elem2 + self.elem2 - self.elem1,
59+
}
60+
}
61+
}
62+
2863
impl<T> fmt::Debug for Fp2Elem<T>
2964
where
3065
T: fmt::Debug,
@@ -175,14 +210,20 @@ where
175210

176211
impl<T> Inv for Fp2Elem<T>
177212
where
178-
T: Pow<u32, Output = T> + Add<Output = T> + Neg<Output = T> + Div<Output = T> + Copy,
213+
T: Pow<u32, Output = T>
214+
+ Add<Output = T>
215+
+ Neg<Output = T>
216+
+ Mul<Output = T>
217+
+ Inv<Output = T>
218+
+ Copy,
179219
{
180220
type Output = Fp2Elem<T>;
181221
fn inv(self) -> Fp2Elem<T> {
182-
let mag = self.elem1.pow(2) + self.elem2.pow(2);
222+
let magnitude = self.elem1.pow(2) + self.elem2.pow(2);
223+
let mag_inv = magnitude.inv();
183224
Fp2Elem {
184-
elem1: (-self.elem1 / mag),
185-
elem2: (self.elem2 / mag),
225+
elem1: (-self.elem1 * mag_inv),
226+
elem2: (self.elem2 * mag_inv),
186227
}
187228
}
188229
}

src/internal/fp6elem.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::internal::bytedecoder::{BytesDecoder, DecodeErr};
22
use crate::internal::field::{ExtensionField, Field};
3-
use crate::internal::fp2elem::Fp2Elem;
3+
use crate::internal::fp2elem::{Fp2Elem, Xi};
44
use crate::internal::hashable::Hashable;
55
use crate::internal::ByteVector;
66
use crate::internal::{pow_for_square, sum_n, Square};
@@ -158,12 +158,11 @@ where
158158

159159
let elem1 = self.elem1 * other.elem3 + self.elem2 * other.elem2 + self.elem3 * other.elem1;
160160

161-
let elem2 = self.elem1 * other.elem1 * ExtensionField::xi()
162-
+ self.elem2 * other.elem3
163-
+ self.elem3 * other.elem2;
161+
let elem2 =
162+
self.elem1 * other.elem1 * Xi + self.elem2 * other.elem3 + self.elem3 * other.elem2;
164163

165-
let elem3 = (self.elem1 * other.elem2 + self.elem2 * other.elem1) * ExtensionField::xi()
166-
+ self.elem3 * other.elem3;
164+
let elem3 =
165+
(self.elem1 * other.elem2 + self.elem2 * other.elem1) * Xi + self.elem3 * other.elem3;
167166

168167
Fp6Elem {
169168
elem1,
@@ -215,8 +214,6 @@ where
215214
{
216215
type Output = Fp6Elem<T>;
217216
fn inv(self) -> Fp6Elem<T> {
218-
let xi: Fp2Elem<T> = ExtensionField::xi();
219-
220217
// Algorithm 5.23 from El Mrabet--Joye 2017 "Guide to Pairing-Based Cryptography."
221218
let (c, b, a) = (self.elem1, self.elem2, self.elem3);
222219
let v0 = a.square();
@@ -225,12 +222,12 @@ where
225222
let v3 = a * b;
226223
let v4 = a * c;
227224
let v5 = b * c;
228-
let cap_a = v0 - xi * v5;
229-
let cap_b = xi * v2 - v3;
225+
let cap_a = v0 - Xi * v5;
226+
let cap_b = Xi * v2 - v3;
230227
let cap_c = v1 - v4;
231228
let v6 = a * cap_a;
232-
let v61 = v6 + (xi * c * cap_b);
233-
let v62 = v61 + (xi * b * cap_c);
229+
let v61 = v6 + (Xi * c * cap_b);
230+
let v62 = v61 + (Xi * b * cap_c);
234231
let cap_f = v62.inv();
235232
let c0 = cap_a * cap_f;
236233
let c1 = cap_b * cap_f;
@@ -269,15 +266,13 @@ where
269266
T: Clone + ExtensionField,
270267
{
271268
fn square(&self) -> Self {
272-
let xi: Fp2Elem<T> = ExtensionField::xi();
273-
274269
let a_prime = Fp2Elem {
275270
elem1: self.elem1.elem1 * 2,
276271
elem2: self.elem1.elem2 * 2,
277272
};
278273
let a2 = a_prime * self.elem3 + self.elem2.square();
279-
let fp22 = self.elem1.square() * xi + self.elem2 * self.elem3 * 2;
280-
let fp32 = (a_prime * self.elem2) * xi + self.elem3.square();
274+
let fp22 = self.elem1.square() * Xi + self.elem2 * self.elem3 * 2;
275+
let fp32 = (a_prime * self.elem2) * Xi + self.elem3.square();
281276
Fp6Elem {
282277
elem1: a2,
283278
elem2: fp22,

src/internal/homogeneouspoint.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,16 +344,13 @@ impl<T: ExtensionField + BytesDecoder> BytesDecoder for TwistedHPoint<T> {
344344
/// Decodes and validates that the resultant TwistedHPoint is on the curve
345345
fn decode(bytes: ByteVector) -> Result<Self, DecodeErr> {
346346
if bytes.len() == Self::ENCODED_SIZE_BYTES {
347-
// 3 / (u + 3)
348-
let twisted_curve_const_coeff: Fp2Elem<T> = ExtensionField::xi().inv() * 3;
349-
350347
let (x_bytes, y_bytes) = bytes.split_at(Self::ENCODED_SIZE_BYTES / 2);
351348
let hpoint = TwistedHPoint::new(
352349
Fp2Elem::<T>::decode(x_bytes.to_vec())?,
353350
Fp2Elem::<T>::decode(y_bytes.to_vec())?,
354351
);
355352

356-
if hpoint.y.pow(2) == (hpoint.x.pow(3) + twisted_curve_const_coeff) {
353+
if hpoint.y.pow(2) == (hpoint.x.pow(3) + ExtensionField::twisted_curve_const_coeff()) {
357354
Result::Ok(hpoint)
358355
} else {
359356
Result::Err(DecodeErr::BytesInvalid {
@@ -438,9 +435,6 @@ where
438435
// "Complete addition formulas for prime order elliptic curves",
439436
// https://eprint.iacr.org/2015/1060
440437
// (For y^2=x^3+b, doubling formulas, page 12.)
441-
// Mind that the main curve uses b = 3, but the twisted curve uses
442-
// b = 3/(u+3). The code below _assumes_ that the twisted curve is used
443-
// when the base field is FP2Elem (this is quite ugly).
444438
fn double<T, U>(x: T, y: T, z: T, three_b: U) -> (T, T, T)
445439
where
446440
T: Field + Copy + Mul<U, Output = T>,

src/internal/pairing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::internal::field::ExtensionField;
22
use crate::internal::fp12elem::Fp12Elem;
3-
use crate::internal::fp2elem::Fp2Elem;
3+
use crate::internal::fp2elem::{Fp2Elem, Xi};
44
use crate::internal::fp6elem::Fp6Elem;
55
use crate::internal::homogeneouspoint::Double;
66
use crate::internal::homogeneouspoint::HomogeneousPoint;
@@ -236,7 +236,7 @@ where
236236
elem2: y,
237237
elem3: x,
238238
} = b2;
239-
let z2 = z * ExtensionField::xi() + One::one();
239+
let z2 = z * Xi + One::one();
240240
Fp12Elem {
241241
elem1: a2,
242242
elem2: Fp6Elem {

0 commit comments

Comments
 (0)