mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-04 20:03:40 +00:00
Merge pull request #134 from Mandragorian/feature-scalar-traits
Implement Product and Sum traits
This commit is contained in:
commit
62bb6b79a1
3 changed files with 180 additions and 2 deletions
|
|
@ -98,6 +98,7 @@ use core::iter::Iterator;
|
|||
use core::ops::{Add, Sub, Neg};
|
||||
use core::ops::{AddAssign, SubAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::iter::Sum;
|
||||
use core::borrow::Borrow;
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
|
|
@ -427,6 +428,19 @@ impl<'b> SubAssign<&'b EdwardsPoint> for EdwardsPoint {
|
|||
|
||||
define_sub_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint);
|
||||
|
||||
impl<T> Sum<T> for EdwardsPoint
|
||||
where
|
||||
T: Borrow<EdwardsPoint>
|
||||
{
|
||||
fn sum<I>(iter: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>
|
||||
{
|
||||
iter.fold(EdwardsPoint::identity(), |acc, item| acc + item.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Negation
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
@ -1092,6 +1106,38 @@ mod test {
|
|||
assert_eq!(bp16.compress(), BASE16_CMPRSSD);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_sum() {
|
||||
|
||||
// Test that sum works for non-empty iterators
|
||||
let BASE = constants::ED25519_BASEPOINT_POINT;
|
||||
|
||||
let s1 = Scalar::from_u64(999);
|
||||
let P1 = &BASE * &s1;
|
||||
|
||||
let s2 = Scalar::from_u64(333);
|
||||
let P2 = &BASE * &s2;
|
||||
|
||||
let vec = vec![P1.clone(), P2.clone()];
|
||||
let sum: EdwardsPoint = vec.iter().sum();
|
||||
|
||||
assert_eq!(sum, P1 + P2);
|
||||
|
||||
// Test that sum works for the empty iterator
|
||||
let empty_vector: Vec<EdwardsPoint> = vec![];
|
||||
let sum: EdwardsPoint = empty_vector.iter().sum();
|
||||
|
||||
assert_eq!(sum, EdwardsPoint::identity());
|
||||
|
||||
// Test that sum works on owning iterators
|
||||
let s = Scalar::from_u64(2);
|
||||
let mapped = vec.iter().map(|x| x * &s);
|
||||
let sum: EdwardsPoint = mapped.sum();
|
||||
|
||||
assert_eq!(sum, &P1 * &s + &P2 * &s);
|
||||
}
|
||||
|
||||
|
||||
/// Test that the conditional assignment trait works for AffineNielsPoints.
|
||||
#[test]
|
||||
fn conditional_assign_for_affine_niels_point() {
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ use core::fmt::Debug;
|
|||
use core::ops::{Add, Sub, Neg};
|
||||
use core::ops::{AddAssign, SubAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::iter::Sum;
|
||||
use core::borrow::Borrow;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
|
|
@ -732,6 +733,18 @@ impl<'b> SubAssign<&'b RistrettoPoint> for RistrettoPoint {
|
|||
|
||||
define_sub_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint);
|
||||
|
||||
impl<T> Sum<T> for RistrettoPoint
|
||||
where
|
||||
T: Borrow<RistrettoPoint>
|
||||
{
|
||||
fn sum<I>(iter: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>
|
||||
{
|
||||
iter.fold(RistrettoPoint::identity(), |acc, item| acc + item.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Neg for &'a RistrettoPoint {
|
||||
type Output = RistrettoPoint;
|
||||
|
||||
|
|
@ -1033,6 +1046,37 @@ mod test {
|
|||
assert!(P1.compress().as_bytes() == P2.compress().as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_sum() {
|
||||
|
||||
// Test that sum works for non-empty iterators
|
||||
let BASE = constants::RISTRETTO_BASEPOINT_POINT;
|
||||
|
||||
let s1 = Scalar::from_u64(999);
|
||||
let P1 = &BASE * &s1;
|
||||
|
||||
let s2 = Scalar::from_u64(333);
|
||||
let P2 = &BASE * &s2;
|
||||
|
||||
let vec = vec![P1.clone(), P2.clone()];
|
||||
let sum: RistrettoPoint = vec.iter().sum();
|
||||
|
||||
assert_eq!(sum, P1 + P2);
|
||||
|
||||
// Test that sum works for the empty iterator
|
||||
let empty_vector: Vec<RistrettoPoint> = vec![];
|
||||
let sum: RistrettoPoint = empty_vector.iter().sum();
|
||||
|
||||
assert_eq!(sum, RistrettoPoint::identity());
|
||||
|
||||
// Test that sum works on owning iterators
|
||||
let s = Scalar::from_u64(2);
|
||||
let mapped = vec.iter().map(|x| x * &s);
|
||||
let sum: RistrettoPoint = mapped.sum();
|
||||
|
||||
assert_eq!(sum, &P1 * &s + &P2 * &s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decompress_negative_s_fails() {
|
||||
// constants::d is neg, so decompression should fail as |d| != d.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ use core::ops::{Sub, SubAssign};
|
|||
use core::ops::{Mul, MulAssign};
|
||||
use core::ops::{Index};
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::iter::{Product, Sum};
|
||||
use core::borrow::Borrow;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use rand::Rng;
|
||||
|
|
@ -293,6 +295,30 @@ impl<'de> Deserialize<'de> for Scalar {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Product<T> for Scalar
|
||||
where
|
||||
T: Borrow<Scalar>
|
||||
{
|
||||
fn product<I>(iter: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>
|
||||
{
|
||||
iter.fold(Scalar::one(), |acc, item| acc * item.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Sum<T> for Scalar
|
||||
where
|
||||
T: Borrow<Scalar>
|
||||
{
|
||||
fn sum<I>(iter: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>
|
||||
{
|
||||
iter.fold(Scalar::zero(), |acc, item| acc + item.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
impl Scalar {
|
||||
/// Return a `Scalar` chosen uniformly at random using a user-provided RNG.
|
||||
///
|
||||
|
|
@ -540,7 +566,7 @@ impl Scalar {
|
|||
/// $$
|
||||
/// k = \sum\_{i=0}\^m k\_i 2^i,
|
||||
/// $$
|
||||
/// and split the sum as
|
||||
/// and split the sum as
|
||||
/// $$
|
||||
/// k = \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \sum\_{i=0} k\_{i+w} 2^i
|
||||
/// $$
|
||||
|
|
@ -581,7 +607,7 @@ impl Scalar {
|
|||
|
||||
let width = 1 << w;
|
||||
let window_mask = width - 1;
|
||||
|
||||
|
||||
let mut pos = 0;
|
||||
let mut carry = 0;
|
||||
while pos < 256 {
|
||||
|
|
@ -912,6 +938,68 @@ mod test {
|
|||
assert_eq!(should_be_X_times_Y, X_TIMES_Y);
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn impl_product() {
|
||||
// Test that product works for non-empty iterators
|
||||
let X_Y_vector = vec![X, Y];
|
||||
let should_be_X_times_Y: Scalar = X_Y_vector.iter().product();
|
||||
assert_eq!(should_be_X_times_Y, X_TIMES_Y);
|
||||
|
||||
// Test that product works for the empty iterator
|
||||
let one = Scalar::one();
|
||||
let empty_vector = vec![];
|
||||
let should_be_one: Scalar = empty_vector.iter().product();
|
||||
assert_eq!(should_be_one, one);
|
||||
|
||||
// Test that product works for iterators where Item = Scalar
|
||||
let xs = [Scalar::from_u64(2); 10];
|
||||
let ys = [Scalar::from_u64(3); 10];
|
||||
// now zs is an iterator with Item = Scalar
|
||||
let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x * y);
|
||||
|
||||
let x_prod: Scalar = xs.iter().product();
|
||||
let y_prod: Scalar = ys.iter().product();
|
||||
let z_prod: Scalar = zs.product();
|
||||
|
||||
assert_eq!(x_prod, Scalar::from_u64(1024));
|
||||
assert_eq!(y_prod, Scalar::from_u64(59049));
|
||||
assert_eq!(z_prod, Scalar::from_u64(60466176));
|
||||
assert_eq!(x_prod * y_prod, z_prod);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_sum() {
|
||||
|
||||
// Test that sum works for non-empty iterators
|
||||
let two = Scalar::from_u64(2);
|
||||
let one_vector = vec![Scalar::one(), Scalar::one()];
|
||||
let should_be_two: Scalar = one_vector.iter().sum();
|
||||
assert_eq!(should_be_two, two);
|
||||
|
||||
// Test that sum works for the empty iterator
|
||||
let zero = Scalar::zero();
|
||||
let empty_vector = vec![];
|
||||
let should_be_zero: Scalar = empty_vector.iter().sum();
|
||||
assert_eq!(should_be_zero, zero);
|
||||
|
||||
// Test that sum works for owned types
|
||||
let xs = [Scalar::from_u64(1); 10];
|
||||
let ys = [Scalar::from_u64(2); 10];
|
||||
// now zs is an iterator with Item = Scalar
|
||||
let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x + y);
|
||||
|
||||
let x_sum: Scalar = xs.iter().sum();
|
||||
let y_sum: Scalar = ys.iter().sum();
|
||||
let z_sum: Scalar = zs.sum();
|
||||
|
||||
assert_eq!(x_sum, Scalar::from_u64(10));
|
||||
assert_eq!(y_sum, Scalar::from_u64(20));
|
||||
assert_eq!(z_sum, Scalar::from_u64(30));
|
||||
assert_eq!(x_sum + y_sum, z_sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn square() {
|
||||
let expected = &X * &X;
|
||||
|
|
|
|||
Loading…
Reference in a new issue