commit
803b6a3e65
|
@ -1,5 +1,9 @@
|
|||
[package]
|
||||
authors = ["Sean Bowe <ewillbefull@gmail.com>", "Eirik Ogilvie-Wigley <eowigley@gmail.com>"]
|
||||
authors = [
|
||||
"Sean Bowe <ewillbefull@gmail.com>",
|
||||
"Eirik Ogilvie-Wigley <eowigley@gmail.com>",
|
||||
"Jack Grigg <thestr4d@gmail.com>",
|
||||
]
|
||||
description = "Implementation of the Jubjub elliptic curve group"
|
||||
documentation = "https://docs.rs/jubjub/"
|
||||
homepage = "https://github.com/zkcrypto/jubjub"
|
||||
|
|
47
src/fq.rs
47
src/fq.rs
|
@ -200,7 +200,7 @@ impl Fq {
|
|||
/// Attempts to convert a little-endian byte representation of
|
||||
/// a field element into an element of `Fq`, failing if the input
|
||||
/// is not canonical (is not smaller than q).
|
||||
pub fn from_bytes(bytes: [u8; 32]) -> CtOption<Fq> {
|
||||
pub fn from_bytes(bytes: &[u8; 32]) -> CtOption<Fq> {
|
||||
let mut tmp = Fq([0, 0, 0, 0]);
|
||||
|
||||
tmp.0[0] = LittleEndian::read_u64(&bytes[0..8]);
|
||||
|
@ -244,7 +244,7 @@ impl Fq {
|
|||
|
||||
/// Converts a 512-bit little endian integer into
|
||||
/// an element of Fq by reducing modulo q.
|
||||
pub fn from_bytes_wide(bytes: [u8; 64]) -> Fq {
|
||||
pub fn from_bytes_wide(bytes: &[u8; 64]) -> Fq {
|
||||
Fq::from_u512([
|
||||
LittleEndian::read_u64(&bytes[0..8]),
|
||||
LittleEndian::read_u64(&bytes[8..16]),
|
||||
|
@ -409,16 +409,15 @@ impl Fq {
|
|||
}
|
||||
}
|
||||
// found using https://github.com/kwantam/addchain
|
||||
let t10 = *self;
|
||||
let t0 = t10.square();
|
||||
let mut t1 = t0 * &t10;
|
||||
let mut t0 = self.square();
|
||||
let mut t1 = t0 * self;
|
||||
let mut t16 = t0.square();
|
||||
let mut t6 = t16.square();
|
||||
let t5 = t6 * &t0;
|
||||
let mut t0 = t6 * &t16;
|
||||
let t12 = t5 * &t16;
|
||||
let mut t5 = t6 * &t0;
|
||||
t0 = t6 * &t16;
|
||||
let mut t12 = t5 * &t16;
|
||||
let mut t2 = t6.square();
|
||||
let t7 = t5 * &t6;
|
||||
let mut t7 = t5 * &t6;
|
||||
let mut t15 = t0 * &t5;
|
||||
let mut t17 = t12.square();
|
||||
t1.mul_assign(&t17);
|
||||
|
@ -426,12 +425,12 @@ impl Fq {
|
|||
let t8 = t1 * &t17;
|
||||
let t4 = t8 * &t2;
|
||||
let t9 = t8 * &t7;
|
||||
let t7 = t4 * &t5;
|
||||
t7 = t4 * &t5;
|
||||
let t11 = t4 * &t17;
|
||||
let t5 = t9 * &t17;
|
||||
t5 = t9 * &t17;
|
||||
let t14 = t7 * &t15;
|
||||
let t13 = t11 * &t12;
|
||||
let t12 = t11 * &t17;
|
||||
t12 = t11 * &t17;
|
||||
t15.mul_assign(&t12);
|
||||
t16.mul_assign(&t15);
|
||||
t3.mul_assign(&t16);
|
||||
|
@ -458,7 +457,7 @@ impl Fq {
|
|||
square_assign_multi(&mut t0, 8);
|
||||
t0.mul_assign(&t8);
|
||||
square_assign_multi(&mut t0, 8);
|
||||
t0.mul_assign(&t10);
|
||||
t0.mul_assign(self);
|
||||
square_assign_multi(&mut t0, 14);
|
||||
t0.mul_assign(&t9);
|
||||
square_assign_multi(&mut t0, 10);
|
||||
|
@ -689,7 +688,7 @@ fn test_into_bytes() {
|
|||
#[test]
|
||||
fn test_from_bytes() {
|
||||
assert_eq!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
])
|
||||
|
@ -698,7 +697,7 @@ fn test_from_bytes() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
])
|
||||
|
@ -707,7 +706,7 @@ fn test_from_bytes() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
254, 255, 255, 255, 1, 0, 0, 0, 2, 72, 3, 0, 250, 183, 132, 88, 245, 79, 188, 236, 239,
|
||||
79, 140, 153, 111, 5, 197, 172, 89, 177, 36, 24
|
||||
])
|
||||
|
@ -717,7 +716,7 @@ fn test_from_bytes() {
|
|||
|
||||
// -1 should work
|
||||
assert!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
0, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
|
||||
216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115
|
||||
])
|
||||
|
@ -728,7 +727,7 @@ fn test_from_bytes() {
|
|||
|
||||
// modulus is invalid
|
||||
assert!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
|
||||
216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115
|
||||
])
|
||||
|
@ -739,7 +738,7 @@ fn test_from_bytes() {
|
|||
|
||||
// Anything larger than the modulus is invalid
|
||||
assert!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
2, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
|
||||
216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115
|
||||
])
|
||||
|
@ -748,7 +747,7 @@ fn test_from_bytes() {
|
|||
== 1
|
||||
);
|
||||
assert!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
|
||||
216, 58, 51, 72, 125, 157, 41, 83, 167, 237, 115
|
||||
])
|
||||
|
@ -757,7 +756,7 @@ fn test_from_bytes() {
|
|||
== 1
|
||||
);
|
||||
assert!(
|
||||
Fq::from_bytes([
|
||||
Fq::from_bytes(&[
|
||||
1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
|
||||
216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 116
|
||||
])
|
||||
|
@ -807,7 +806,7 @@ fn test_from_u512_max() {
|
|||
fn test_from_bytes_wide_r2() {
|
||||
assert_eq!(
|
||||
R2,
|
||||
Fq::from_bytes_wide([
|
||||
Fq::from_bytes_wide(&[
|
||||
254, 255, 255, 255, 1, 0, 0, 0, 2, 72, 3, 0, 250, 183, 132, 88, 245, 79, 188, 236, 239,
|
||||
79, 140, 153, 111, 5, 197, 172, 89, 177, 36, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -819,7 +818,7 @@ fn test_from_bytes_wide_r2() {
|
|||
fn test_from_bytes_wide_negative_one() {
|
||||
assert_eq!(
|
||||
-&Fq::one(),
|
||||
Fq::from_bytes_wide([
|
||||
Fq::from_bytes_wide(&[
|
||||
0, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
|
||||
216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -836,7 +835,7 @@ fn test_from_bytes_wide_maximum() {
|
|||
0xda44ec81daf9a422,
|
||||
0x5605aa601c162e79
|
||||
]),
|
||||
Fq::from_bytes_wide([0xff; 64])
|
||||
Fq::from_bytes_wide(&[0xff; 64])
|
||||
);
|
||||
}
|
||||
|
||||
|
|
51
src/fr.rs
51
src/fr.rs
|
@ -189,7 +189,7 @@ impl Fr {
|
|||
/// Attempts to convert a little-endian byte representation of
|
||||
/// a field element into an element of `Fr`, failing if the input
|
||||
/// is not canonical (is not smaller than r).
|
||||
pub fn from_bytes(bytes: [u8; 32]) -> CtOption<Fr> {
|
||||
pub fn from_bytes(bytes: &[u8; 32]) -> CtOption<Fr> {
|
||||
let mut tmp = Fr([0, 0, 0, 0]);
|
||||
|
||||
tmp.0[0] = LittleEndian::read_u64(&bytes[0..8]);
|
||||
|
@ -233,7 +233,7 @@ impl Fr {
|
|||
|
||||
/// Converts a 512-bit little endian integer into
|
||||
/// an element of Fr by reducing modulo r.
|
||||
pub fn from_bytes_wide(bytes: [u8; 64]) -> Fr {
|
||||
pub fn from_bytes_wide(bytes: &[u8; 64]) -> Fr {
|
||||
Fr::from_u512([
|
||||
LittleEndian::read_u64(&bytes[0..8]),
|
||||
LittleEndian::read_u64(&bytes[8..16]),
|
||||
|
@ -367,11 +367,10 @@ impl Fr {
|
|||
}
|
||||
}
|
||||
// found using https://github.com/kwantam/addchain
|
||||
let t10 = *self;
|
||||
let t1 = t10.square();
|
||||
let t0 = t1.square();
|
||||
let t3 = t0 * &t1;
|
||||
let t6 = t3 * &t10;
|
||||
let mut t1 = self.square();
|
||||
let mut t0 = t1.square();
|
||||
let mut t3 = t0 * &t1;
|
||||
let t6 = t3 * self;
|
||||
let t7 = t6 * &t1;
|
||||
let t12 = t7 * &t3;
|
||||
let t13 = t12 * &t0;
|
||||
|
@ -386,10 +385,10 @@ impl Fr {
|
|||
let t8 = t18 * &t3;
|
||||
let t17 = t14 * &t3;
|
||||
let t11 = t8 * &t3;
|
||||
let t1 = t17 * &t3;
|
||||
t1 = t17 * &t3;
|
||||
let t5 = t11 * &t3;
|
||||
let t3 = t5 * &t0;
|
||||
let mut t0 = t5.square();
|
||||
t3 = t5 * &t0;
|
||||
t0 = t5.square();
|
||||
square_assign_multi(&mut t0, 5);
|
||||
t0.mul_assign(&t3);
|
||||
square_assign_multi(&mut t0, 6);
|
||||
|
@ -407,7 +406,7 @@ impl Fr {
|
|||
square_assign_multi(&mut t0, 5);
|
||||
t0.mul_assign(&t16);
|
||||
square_assign_multi(&mut t0, 3);
|
||||
t0.mul_assign(&t10);
|
||||
t0.mul_assign(self);
|
||||
square_assign_multi(&mut t0, 11);
|
||||
t0.mul_assign(&t11);
|
||||
square_assign_multi(&mut t0, 8);
|
||||
|
@ -415,7 +414,7 @@ impl Fr {
|
|||
square_assign_multi(&mut t0, 5);
|
||||
t0.mul_assign(&t15);
|
||||
square_assign_multi(&mut t0, 8);
|
||||
t0.mul_assign(&t10);
|
||||
t0.mul_assign(self);
|
||||
square_assign_multi(&mut t0, 12);
|
||||
t0.mul_assign(&t13);
|
||||
square_assign_multi(&mut t0, 7);
|
||||
|
@ -427,9 +426,9 @@ impl Fr {
|
|||
square_assign_multi(&mut t0, 5);
|
||||
t0.mul_assign(&t13);
|
||||
square_assign_multi(&mut t0, 2);
|
||||
t0.mul_assign(&t10);
|
||||
t0.mul_assign(self);
|
||||
square_assign_multi(&mut t0, 6);
|
||||
t0.mul_assign(&t10);
|
||||
t0.mul_assign(self);
|
||||
square_assign_multi(&mut t0, 9);
|
||||
t0.mul_assign(&t7);
|
||||
square_assign_multi(&mut t0, 6);
|
||||
|
@ -437,7 +436,7 @@ impl Fr {
|
|||
square_assign_multi(&mut t0, 8);
|
||||
t0.mul_assign(&t11);
|
||||
square_assign_multi(&mut t0, 3);
|
||||
t0.mul_assign(&t10);
|
||||
t0.mul_assign(self);
|
||||
square_assign_multi(&mut t0, 12);
|
||||
t0.mul_assign(&t9);
|
||||
square_assign_multi(&mut t0, 11);
|
||||
|
@ -642,7 +641,7 @@ fn test_into_bytes() {
|
|||
#[test]
|
||||
fn test_from_bytes() {
|
||||
assert_eq!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
])
|
||||
|
@ -651,7 +650,7 @@ fn test_from_bytes() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
])
|
||||
|
@ -660,7 +659,7 @@ fn test_from_bytes() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
217, 7, 150, 185, 179, 11, 248, 37, 80, 231, 182, 102, 47, 214, 21, 243, 244, 20, 136,
|
||||
235, 238, 20, 37, 147, 198, 85, 145, 71, 111, 252, 166, 9
|
||||
])
|
||||
|
@ -670,7 +669,7 @@ fn test_from_bytes() {
|
|||
|
||||
// -1 should work
|
||||
assert!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
182, 44, 247, 214, 94, 14, 151, 208, 130, 16, 200, 204, 147, 32, 104, 166, 0, 59, 52,
|
||||
1, 1, 59, 103, 6, 169, 175, 51, 101, 234, 180, 125, 14
|
||||
])
|
||||
|
@ -681,7 +680,7 @@ fn test_from_bytes() {
|
|||
|
||||
// modulus is invalid
|
||||
assert!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
183, 44, 247, 214, 94, 14, 151, 208, 130, 16, 200, 204, 147, 32, 104, 166, 0, 59, 52,
|
||||
1, 1, 59, 103, 6, 169, 175, 51, 101, 234, 180, 125, 14
|
||||
])
|
||||
|
@ -692,7 +691,7 @@ fn test_from_bytes() {
|
|||
|
||||
// Anything larger than the modulus is invalid
|
||||
assert!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
184, 44, 247, 214, 94, 14, 151, 208, 130, 16, 200, 204, 147, 32, 104, 166, 0, 59, 52,
|
||||
1, 1, 59, 103, 6, 169, 175, 51, 101, 234, 180, 125, 14
|
||||
])
|
||||
|
@ -702,7 +701,7 @@ fn test_from_bytes() {
|
|||
);
|
||||
|
||||
assert!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
183, 44, 247, 214, 94, 14, 151, 208, 130, 16, 200, 204, 147, 32, 104, 166, 0, 59, 52,
|
||||
1, 1, 59, 104, 6, 169, 175, 51, 101, 234, 180, 125, 14
|
||||
])
|
||||
|
@ -712,7 +711,7 @@ fn test_from_bytes() {
|
|||
);
|
||||
|
||||
assert!(
|
||||
Fr::from_bytes([
|
||||
Fr::from_bytes(&[
|
||||
183, 44, 247, 214, 94, 14, 151, 208, 130, 16, 200, 204, 147, 32, 104, 166, 0, 59, 52,
|
||||
1, 1, 59, 103, 6, 169, 175, 51, 101, 234, 180, 125, 15
|
||||
])
|
||||
|
@ -762,7 +761,7 @@ fn test_from_u512_max() {
|
|||
fn test_from_bytes_wide_r2() {
|
||||
assert_eq!(
|
||||
R2,
|
||||
Fr::from_bytes_wide([
|
||||
Fr::from_bytes_wide(&[
|
||||
217, 7, 150, 185, 179, 11, 248, 37, 80, 231, 182, 102, 47, 214, 21, 243, 244, 20, 136,
|
||||
235, 238, 20, 37, 147, 198, 85, 145, 71, 111, 252, 166, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -774,7 +773,7 @@ fn test_from_bytes_wide_r2() {
|
|||
fn test_from_bytes_wide_negative_one() {
|
||||
assert_eq!(
|
||||
-&Fr::one(),
|
||||
Fr::from_bytes_wide([
|
||||
Fr::from_bytes_wide(&[
|
||||
182, 44, 247, 214, 94, 14, 151, 208, 130, 16, 200, 204, 147, 32, 104, 166, 0, 59, 52,
|
||||
1, 1, 59, 103, 6, 169, 175, 51, 101, 234, 180, 125, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -791,7 +790,7 @@ fn test_from_bytes_wide_maximum() {
|
|||
0x6440c91261da51b3,
|
||||
0xa5e07ffb20991cf
|
||||
]),
|
||||
Fr::from_bytes_wide([0xff; 64])
|
||||
Fr::from_bytes_wide(&[0xff; 64])
|
||||
);
|
||||
}
|
||||
|
||||
|
|
128
src/lib.rs
128
src/lib.rs
|
@ -176,13 +176,13 @@ impl From<AffinePoint> for ExtendedPoint {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ExtendedPoint> for AffinePoint {
|
||||
impl<'a> From<&'a ExtendedPoint> for AffinePoint {
|
||||
/// Constructs an affine point from an extended point
|
||||
/// using the map `(U, V, Z, T1, T2) => (U/Z, V/Z)`
|
||||
/// as Z is always nonzero. **This requires a field inversion
|
||||
/// and so it is recommended to perform these in a batch
|
||||
/// using [`batch_normalize`](crate::batch_normalize) instead.**
|
||||
fn from(extended: ExtendedPoint) -> AffinePoint {
|
||||
fn from(extended: &'a ExtendedPoint) -> AffinePoint {
|
||||
// Z coordinate is always nonzero, so this is
|
||||
// its inverse.
|
||||
let zinv = extended.z.invert().unwrap();
|
||||
|
@ -194,6 +194,12 @@ impl From<ExtendedPoint> for AffinePoint {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ExtendedPoint> for AffinePoint {
|
||||
fn from(extended: ExtendedPoint) -> AffinePoint {
|
||||
AffinePoint::from(&extended)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a pre-processed version of an affine point `(u, v)`
|
||||
/// in the form `(v + u, v - u, u * v * 2d)`. This can be added to an
|
||||
/// [`ExtendedPoint`](crate::ExtendedPoint).
|
||||
|
@ -213,8 +219,49 @@ impl AffineNielsPoint {
|
|||
t2d: Fq::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn multiply(&self, by: &[u8; 32]) -> ExtendedPoint {
|
||||
let zero = AffineNielsPoint::identity();
|
||||
|
||||
let mut acc = ExtendedPoint::identity();
|
||||
|
||||
// This is a simple double-and-add implementation of point
|
||||
// multiplication, moving from most significant to least
|
||||
// significant bit of the scalar.
|
||||
//
|
||||
// We skip the leading four bits because they're always
|
||||
// unset for Fr.
|
||||
for bit in by
|
||||
.iter()
|
||||
.rev()
|
||||
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
|
||||
.skip(4)
|
||||
{
|
||||
acc = acc.double();
|
||||
acc += AffineNielsPoint::conditional_select(&zero, &self, bit);
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
|
||||
/// Multiplies this point by the specific little-endian bit pattern in the
|
||||
/// given byte array, ignoring the highest four bits.
|
||||
pub fn multiply_bits(&self, by: &[u8; 32]) -> ExtendedPoint {
|
||||
self.multiply(by)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Mul<&'b Fr> for &'a AffineNielsPoint {
|
||||
type Output = ExtendedPoint;
|
||||
|
||||
fn mul(self, other: &'b Fr) -> ExtendedPoint {
|
||||
self.multiply(&other.into_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl_binops_multiplicative_mixed!(AffineNielsPoint, Fr, ExtendedPoint);
|
||||
|
||||
impl ConditionallySelectable for AffineNielsPoint {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
AffineNielsPoint {
|
||||
|
@ -256,8 +303,49 @@ impl ExtendedNielsPoint {
|
|||
t2d: Fq::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn multiply(&self, by: &[u8; 32]) -> ExtendedPoint {
|
||||
let zero = ExtendedNielsPoint::identity();
|
||||
|
||||
let mut acc = ExtendedPoint::identity();
|
||||
|
||||
// This is a simple double-and-add implementation of point
|
||||
// multiplication, moving from most significant to least
|
||||
// significant bit of the scalar.
|
||||
//
|
||||
// We skip the leading four bits because they're always
|
||||
// unset for Fr.
|
||||
for bit in by
|
||||
.iter()
|
||||
.rev()
|
||||
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
|
||||
.skip(4)
|
||||
{
|
||||
acc = acc.double();
|
||||
acc += ExtendedNielsPoint::conditional_select(&zero, &self, bit);
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
|
||||
/// Multiplies this point by the specific little-endian bit pattern in the
|
||||
/// given byte array, ignoring the highest four bits.
|
||||
pub fn multiply_bits(&self, by: &[u8; 32]) -> ExtendedPoint {
|
||||
self.multiply(by)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Mul<&'b Fr> for &'a ExtendedNielsPoint {
|
||||
type Output = ExtendedPoint;
|
||||
|
||||
fn mul(self, other: &'b Fr) -> ExtendedPoint {
|
||||
self.multiply(&other.into_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl_binops_multiplicative_mixed!(ExtendedNielsPoint, Fr, ExtendedPoint);
|
||||
|
||||
// `d = -(10240/10241)`
|
||||
const EDWARDS_D: Fq = Fq::from_raw([
|
||||
0x01065fd6d6343eb1,
|
||||
|
@ -332,7 +420,7 @@ impl AffinePoint {
|
|||
b[31] &= 0b0111_1111;
|
||||
|
||||
// Interpret what remains as the v-coordinate
|
||||
Fq::from_bytes(b).and_then(|v| {
|
||||
Fq::from_bytes(&b).and_then(|v| {
|
||||
// -u^2 + v^2 = 1 + d.u^2.v^2
|
||||
// -u^2 = 1 + d.u^2.v^2 - v^2 (rearrange)
|
||||
// -u^2 - d.u^2.v^2 = 1 - v^2 (rearrange)
|
||||
|
@ -551,28 +639,7 @@ impl ExtendedPoint {
|
|||
|
||||
#[inline]
|
||||
fn multiply(self, by: &[u8; 32]) -> Self {
|
||||
let zero = ExtendedPoint::identity().to_niels();
|
||||
let base = self.to_niels();
|
||||
|
||||
let mut acc = ExtendedPoint::identity();
|
||||
|
||||
// This is a simple double-and-add implementation of point
|
||||
// multiplication, moving from most significant to least
|
||||
// significant bit of the scalar.
|
||||
//
|
||||
// We skip the leading four bits because they're always
|
||||
// unset for Fr.
|
||||
for bit in by
|
||||
.iter()
|
||||
.rev()
|
||||
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
|
||||
.skip(4)
|
||||
{
|
||||
acc = acc.double();
|
||||
acc = acc + ExtendedNielsPoint::conditional_select(&zero, &base, bit);
|
||||
}
|
||||
|
||||
acc
|
||||
self.to_niels().multiply(by)
|
||||
}
|
||||
|
||||
/// This is only for debugging purposes and not
|
||||
|
@ -1159,6 +1226,17 @@ fn test_mul_consistency() {
|
|||
})
|
||||
.mul_by_cofactor();
|
||||
assert_eq!(p * c, (p * a) * b);
|
||||
|
||||
// Test Mul implemented on ExtendedNielsPoint
|
||||
assert_eq!(p * c, (p.to_niels() * a) * b);
|
||||
assert_eq!(p.to_niels() * c, (p * a) * b);
|
||||
assert_eq!(p.to_niels() * c, (p.to_niels() * a) * b);
|
||||
|
||||
// Test Mul implemented on AffineNielsPoint
|
||||
let p_affine_niels = AffinePoint::from(p).to_niels();
|
||||
assert_eq!(p * c, (p_affine_niels * a) * b);
|
||||
assert_eq!(p_affine_niels * c, (p * a) * b);
|
||||
assert_eq!(p_affine_niels * c, (p_affine_niels * a) * b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
22
src/util.rs
22
src/util.rs
|
@ -105,34 +105,40 @@ macro_rules! impl_binops_additive {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_binops_multiplicative {
|
||||
($lhs:ident, $rhs:ident) => {
|
||||
macro_rules! impl_binops_multiplicative_mixed {
|
||||
($lhs:ident, $rhs:ident, $output:ident) => {
|
||||
impl<'b> Mul<&'b $rhs> for $lhs {
|
||||
type Output = $lhs;
|
||||
type Output = $output;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: &'b $rhs) -> $lhs {
|
||||
fn mul(self, rhs: &'b $rhs) -> $output {
|
||||
&self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$rhs> for &'a $lhs {
|
||||
type Output = $lhs;
|
||||
type Output = $output;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: $rhs) -> $lhs {
|
||||
fn mul(self, rhs: $rhs) -> $output {
|
||||
self * &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$rhs> for $lhs {
|
||||
type Output = $lhs;
|
||||
type Output = $output;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: $rhs) -> $lhs {
|
||||
fn mul(self, rhs: $rhs) -> $output {
|
||||
&self * &rhs
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_binops_multiplicative {
|
||||
($lhs:ident, $rhs:ident) => {
|
||||
impl_binops_multiplicative_mixed!($lhs, $rhs, $lhs);
|
||||
|
||||
impl MulAssign<$rhs> for $lhs {
|
||||
#[inline]
|
||||
|
|
|
@ -16,7 +16,7 @@ impl MyRandom for Fq {
|
|||
fn new_random<T: RngCore>(rng: &mut T) -> Self {
|
||||
let mut random_bytes = [0u8; 64];
|
||||
rng.fill_bytes(&mut random_bytes);
|
||||
Fq::from_bytes_wide(random_bytes)
|
||||
Fq::from_bytes_wide(&random_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,6 @@ impl MyRandom for Fr {
|
|||
fn new_random<T: RngCore>(rng: &mut T) -> Self {
|
||||
let mut random_bytes = [0u8; 64];
|
||||
rng.fill_bytes(&mut random_bytes);
|
||||
Fr::from_bytes_wide(random_bytes)
|
||||
Fr::from_bytes_wide(&random_bytes)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ fn test_to_and_from_bytes() {
|
|||
let mut rng = new_rng();
|
||||
for _ in 0..NUM_BLACK_BOX_CHECKS {
|
||||
let a = Fq::new_random(&mut rng);
|
||||
assert_eq!(a, Fq::from_bytes(Fq::into_bytes(&a)).unwrap());
|
||||
assert_eq!(a, Fq::from_bytes(&Fq::into_bytes(&a)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ fn test_to_and_from_bytes() {
|
|||
let mut rng = new_rng();
|
||||
for _ in 0..NUM_BLACK_BOX_CHECKS {
|
||||
let a = Fr::new_random(&mut rng);
|
||||
assert_eq!(a, Fr::from_bytes(Fr::into_bytes(&a)).unwrap());
|
||||
assert_eq!(a, Fr::from_bytes(&Fr::into_bytes(&a)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue