From 3369bebcff7f471068b0caac6eddef2f58ebe003 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Thu, 9 Nov 2023 17:00:59 +0200 Subject: [PATCH 01/39] Introduced `InvertBatch` and implemented --- elliptic-curve/src/ops.rs | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index b7e9e3d46..6958fe77d 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -4,6 +4,7 @@ pub use core::ops::{Add, AddAssign, Mul, Neg, Shr, ShrAssign, Sub, SubAssign}; use crypto_bigint::Integer; use group::Group; +use subtle::{Choice, ConditionallySelectable, CtOption}; /// Perform an inversion on a field element (i.e. base field element or scalar) pub trait Invert { @@ -25,6 +26,77 @@ pub trait Invert { } } +/// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) +/// at an amortized cost that should be practically as efficient as a single inversion. +pub trait InvertBatch: Invert + Sized { + /// The output type of batch inversion. + /// Since inversion is performed in-place, the outputted value doesn't contain inverses of field elements. + /// Instead, it should be set to `Choice` when inversion may fail or `()` if it always succeeds. + type Output; + + /// Invert a batch of field elements in-place. + fn invert_batch_generic(field_elements: &mut [Self; N]) -> ::Output; + + /// Invert a batch of field elements in-place. + #[cfg(feature = "alloc")] + fn invert_batch(field_elements: &mut alloc::vec::Vec) -> ::Output; +} + +// TODO: safe to assume here that invert performs inversion and not negation (i.e. that we're in multiplicative notation and `Mul` is the write operator)? +// If not, should we take it as another generic? +impl> + Mul + Default + ConditionallySelectable> InvertBatch for T { + type Output = Choice; + + fn invert_batch_generic(field_elements: &mut [Self; N]) -> ::Output { + let mut field_elements_multiples = [field_elements[0]; N]; + let mut field_elements_multiples_inverses = [field_elements[0]; N]; + + invert_helper(field_elements, &mut field_elements_multiples, &mut field_elements_multiples_inverses) + } + + #[cfg(feature = "alloc")] + fn invert_batch(field_elements: &mut alloc::vec::Vec) -> ::Output { + let mut field_elements_multiples = field_elements.clone(); + let mut field_elements_multiples_inverses = field_elements.clone(); + + invert_helper(field_elements.as_mut(), field_elements_multiples.as_mut(), field_elements_multiples_inverses.as_mut()) + } +} + +/// An in-place implementation of "Montgomery's trick". +/// +/// Which is a trick for computing many modular inverses at once +/// by reducing the problem of computing `n` inverses to computing a single inversion, +/// plus some storage and `O(n)` extra multiplications. +/// +/// See: https://iacr.org/archive/pkc2004/29470042/29470042.pdf section 2.2. +fn invert_helper> + Mul + Default + ConditionallySelectable>(field_elements: &mut [T], field_elements_multiples: &mut [T], field_elements_multiples_inverses: &mut [T]) -> Choice { + let batch_size = field_elements.len(); + if batch_size == 0 || batch_size != field_elements_multiples.len() || batch_size != field_elements_multiples_inverses.len() { + return Choice::from(0); + } + + field_elements_multiples[0] = field_elements[0]; + for i in 1..batch_size { + // $ a_n = a_{n-1}*x_n $ + field_elements_multiples[i] = field_elements_multiples[i-1] * field_elements[i]; + } + + field_elements_multiples[batch_size - 1].invert().map(|multiple_of_inverses_of_all_field_elements| { + field_elements_multiples_inverses[batch_size - 1] = multiple_of_inverses_of_all_field_elements; + for i in (1..batch_size).rev() { + // $ a_{n-1} = {a_n}^{-1}*x_n $ + field_elements_multiples_inverses[i-1] = field_elements_multiples_inverses[i] * field_elements[i]; + } + + field_elements[0] = field_elements_multiples_inverses[0]; + for i in 1..batch_size { + // $ {x_n}^{-1} = a_{n}^{-1}*a_{n-1} $ + field_elements[i] = field_elements_multiples_inverses[i] * field_elements_multiples[i-1]; + } + }).is_some() +} + /// Linear combination. /// /// This trait enables crates to provide an optimized implementation of From 3436859ac2a9c5bcaa4afe7631db11d36f2bc9ae Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 12:43:17 +0200 Subject: [PATCH 02/39] Update elliptic-curve/src/ops.rs --- elliptic-curve/src/ops.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 6958fe77d..a02f7a979 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -42,7 +42,6 @@ pub trait InvertBatch: Invert + Sized { fn invert_batch(field_elements: &mut alloc::vec::Vec) -> ::Output; } -// TODO: safe to assume here that invert performs inversion and not negation (i.e. that we're in multiplicative notation and `Mul` is the write operator)? // If not, should we take it as another generic? impl> + Mul + Default + ConditionallySelectable> InvertBatch for T { type Output = Choice; From 1b235abad267ebba40f1618e68c350348850f05a Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 12:44:09 +0200 Subject: [PATCH 03/39] Using `Choice` as the hard-coded `Output` for `InvertBatch` --- elliptic-curve/src/ops.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 6958fe77d..b4d13b8ca 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -29,25 +29,18 @@ pub trait Invert { /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) /// at an amortized cost that should be practically as efficient as a single inversion. pub trait InvertBatch: Invert + Sized { - /// The output type of batch inversion. - /// Since inversion is performed in-place, the outputted value doesn't contain inverses of field elements. - /// Instead, it should be set to `Choice` when inversion may fail or `()` if it always succeeds. - type Output; - /// Invert a batch of field elements in-place. - fn invert_batch_generic(field_elements: &mut [Self; N]) -> ::Output; + fn invert_batch_generic(field_elements: &mut [Self; N]) -> Choice; /// Invert a batch of field elements in-place. #[cfg(feature = "alloc")] - fn invert_batch(field_elements: &mut alloc::vec::Vec) -> ::Output; + fn invert_batch(field_elements: &mut alloc::vec::Vec) -> Choice; } // TODO: safe to assume here that invert performs inversion and not negation (i.e. that we're in multiplicative notation and `Mul` is the write operator)? // If not, should we take it as another generic? impl> + Mul + Default + ConditionallySelectable> InvertBatch for T { - type Output = Choice; - - fn invert_batch_generic(field_elements: &mut [Self; N]) -> ::Output { + fn invert_batch_generic(field_elements: &mut [Self; N]) -> Choice { let mut field_elements_multiples = [field_elements[0]; N]; let mut field_elements_multiples_inverses = [field_elements[0]; N]; @@ -55,7 +48,7 @@ impl> + Mul + Default + C } #[cfg(feature = "alloc")] - fn invert_batch(field_elements: &mut alloc::vec::Vec) -> ::Output { + fn invert_batch(field_elements: &mut alloc::vec::Vec) -> Choice { let mut field_elements_multiples = field_elements.clone(); let mut field_elements_multiples_inverses = field_elements.clone(); From 646044384335c2ecf5d6f23daed703c102b398bd Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 12:44:57 +0200 Subject: [PATCH 04/39] removed comment --- elliptic-curve/src/ops.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index f86b54d3f..c8c2ca9a8 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -37,7 +37,6 @@ pub trait InvertBatch: Invert + Sized { fn invert_batch(field_elements: &mut alloc::vec::Vec) -> Choice; } -// If not, should we take it as another generic? impl> + Mul + Default + ConditionallySelectable> InvertBatch for T { fn invert_batch_generic(field_elements: &mut [Self; N]) -> Choice { let mut field_elements_multiples = [field_elements[0]; N]; From 2a3d0c402159a79a88b2e8f82545c947708e9bd7 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 12:53:14 +0200 Subject: [PATCH 05/39] Taking slice instead of vector --- elliptic-curve/src/ops.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index c8c2ca9a8..a7cc4fcb7 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -34,10 +34,10 @@ pub trait InvertBatch: Invert + Sized { /// Invert a batch of field elements in-place. #[cfg(feature = "alloc")] - fn invert_batch(field_elements: &mut alloc::vec::Vec) -> Choice; + fn invert_batch(field_elements: &mut [Self]) -> Choice; } -impl> + Mul + Default + ConditionallySelectable> InvertBatch for T { +impl> + Mul + Copy + Default + ConditionallySelectable> InvertBatch for T { fn invert_batch_generic(field_elements: &mut [Self; N]) -> Choice { let mut field_elements_multiples = [field_elements[0]; N]; let mut field_elements_multiples_inverses = [field_elements[0]; N]; @@ -46,9 +46,9 @@ impl> + Mul + Default + C } #[cfg(feature = "alloc")] - fn invert_batch(field_elements: &mut alloc::vec::Vec) -> Choice { - let mut field_elements_multiples = field_elements.clone(); - let mut field_elements_multiples_inverses = field_elements.clone(); + fn invert_batch(field_elements: &mut [Self]) -> Choice { + let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()).map(|i| field_elements[i]).collect(); + let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements.len()).map(|i| field_elements[i]).collect(); invert_helper(field_elements.as_mut(), field_elements_multiples.as_mut(), field_elements_multiples_inverses.as_mut()) } From 769427069b3edb2e537b211f5aa594301b335d05 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 13:13:36 +0200 Subject: [PATCH 06/39] not in-place --- elliptic-curve/src/ops.rs | 112 +++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 32 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index a7cc4fcb7..fe3d66f17 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -29,63 +29,111 @@ pub trait Invert { /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) /// at an amortized cost that should be practically as efficient as a single inversion. pub trait InvertBatch: Invert + Sized { - /// Invert a batch of field elements in-place. - fn invert_batch_generic(field_elements: &mut [Self; N]) -> Choice; + /// Invert a batch of field elements. + fn invert_batch_generic(field_elements: &[Self; N]) -> CtOption<[Self; N]>; - /// Invert a batch of field elements in-place. + /// Invert a batch of field elements. #[cfg(feature = "alloc")] - fn invert_batch(field_elements: &mut [Self]) -> Choice; + fn invert_batch>(field_elements: &[Self]) -> CtOption; } -impl> + Mul + Copy + Default + ConditionallySelectable> InvertBatch for T { - fn invert_batch_generic(field_elements: &mut [Self; N]) -> Choice { +impl< + T: Invert> + + Mul + + Copy + + Default + + ConditionallySelectable, + > InvertBatch for T +{ + fn invert_batch_generic(field_elements: &[Self; N]) -> CtOption<[Self; N]> { let mut field_elements_multiples = [field_elements[0]; N]; let mut field_elements_multiples_inverses = [field_elements[0]; N]; + let mut field_elements_inverses = [field_elements[0]; N]; - invert_helper(field_elements, &mut field_elements_multiples, &mut field_elements_multiples_inverses) + let inversion_succeeded = invert_helper( + field_elements, + &mut field_elements_multiples, + &mut field_elements_multiples_inverses, + &mut field_elements_inverses, + ); + + CtOption::new(field_elements_inverses, inversion_succeeded) } #[cfg(feature = "alloc")] - fn invert_batch(field_elements: &mut [Self]) -> Choice { - let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()).map(|i| field_elements[i]).collect(); - let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements.len()).map(|i| field_elements[i]).collect(); - - invert_helper(field_elements.as_mut(), field_elements_multiples.as_mut(), field_elements_multiples_inverses.as_mut()) + fn invert_batch>(field_elements: &[Self]) -> CtOption { + let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()) + .map(|i| field_elements[i]) + .collect(); + let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements + .len()) + .map(|i| field_elements[i]) + .collect(); + let mut field_elements_inverses: alloc::vec::Vec = (0..field_elements.len()) + .map(|i| field_elements[i]) + .collect(); + + let inversion_succeeded = invert_helper( + field_elements, + field_elements_multiples.as_mut(), + field_elements_multiples_inverses.as_mut(), + field_elements_inverses.as_mut(), + ); + + CtOption::new( + field_elements_inverses.into_iter().collect(), + inversion_succeeded, + ) } } -/// An in-place implementation of "Montgomery's trick". +/// Implements "Montgomery's trick", a trick for computing many modular inverses at once. /// -/// Which is a trick for computing many modular inverses at once -/// by reducing the problem of computing `n` inverses to computing a single inversion, -/// plus some storage and `O(n)` extra multiplications. +/// "Montgomery's trick" works by reducing the problem of computing `n` inverses +/// to computing a single inversion, plus some storage and `O(n)` extra multiplications. /// /// See: https://iacr.org/archive/pkc2004/29470042/29470042.pdf section 2.2. -fn invert_helper> + Mul + Default + ConditionallySelectable>(field_elements: &mut [T], field_elements_multiples: &mut [T], field_elements_multiples_inverses: &mut [T]) -> Choice { +fn invert_helper< + T: Invert> + Mul + Default + ConditionallySelectable, +>( + field_elements: &[T], + field_elements_multiples: &mut [T], + field_elements_multiples_inverses: &mut [T], + field_elements_inverses: &mut [T], +) -> Choice { let batch_size = field_elements.len(); - if batch_size == 0 || batch_size != field_elements_multiples.len() || batch_size != field_elements_multiples_inverses.len() { + if batch_size == 0 + || batch_size != field_elements_multiples.len() + || batch_size != field_elements_multiples_inverses.len() + { return Choice::from(0); } field_elements_multiples[0] = field_elements[0]; for i in 1..batch_size { // $ a_n = a_{n-1}*x_n $ - field_elements_multiples[i] = field_elements_multiples[i-1] * field_elements[i]; + field_elements_multiples[i] = field_elements_multiples[i - 1] * field_elements[i]; } - field_elements_multiples[batch_size - 1].invert().map(|multiple_of_inverses_of_all_field_elements| { - field_elements_multiples_inverses[batch_size - 1] = multiple_of_inverses_of_all_field_elements; - for i in (1..batch_size).rev() { - // $ a_{n-1} = {a_n}^{-1}*x_n $ - field_elements_multiples_inverses[i-1] = field_elements_multiples_inverses[i] * field_elements[i]; - } - - field_elements[0] = field_elements_multiples_inverses[0]; - for i in 1..batch_size { - // $ {x_n}^{-1} = a_{n}^{-1}*a_{n-1} $ - field_elements[i] = field_elements_multiples_inverses[i] * field_elements_multiples[i-1]; - } - }).is_some() + field_elements_multiples[batch_size - 1] + .invert() + .map(|multiple_of_inverses_of_all_field_elements| { + field_elements_multiples_inverses[batch_size - 1] = + multiple_of_inverses_of_all_field_elements; + for i in (1..batch_size).rev() { + // $ a_{n-1} = {a_n}^{-1}*x_n $ + field_elements_multiples_inverses[i - 1] = + field_elements_multiples_inverses[i] * field_elements[i]; + } + + field_elements_inverses[0] = field_elements_multiples_inverses[0]; + for i in 1..batch_size { + // $ {x_n}^{-1} = a_{n}^{-1}*a_{n-1} $ + field_elements_inverses[i] = + field_elements_multiples_inverses[i] * field_elements_multiples[i - 1]; + } + }) + .is_some() } /// Linear combination. From e8c3ea252adb30ba0bd56904805a1afd64532780 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 13:15:40 +0200 Subject: [PATCH 07/39] `ToAffineBatch` --- elliptic-curve/src/arithmetic.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 7ef7fc53d..87735d126 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -84,3 +84,16 @@ pub trait PrimeCurveArithmetic: /// Prime order elliptic curve group. type CurveGroup: group::prime::PrimeCurve::AffinePoint>; } + +pub trait ToAffineBatch: CurveArithmetic { + /// Converts a batch of points in their projective representation into the affine ones. + fn batch_to_affine_generic( + points: [Self::ProjectivePoint; N], + ) -> [Self::AffinePoint; N]; + + /// Converts a batch of points in their projective representation into the affine ones. + #[cfg(feature = "alloc")] + fn batch_to_affine>( + points: alloc::vec::Vec, + ) -> B; +} From 71521a50d7a6b28698467e6662209f624899bba9 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 14:50:39 +0200 Subject: [PATCH 08/39] temporary set `version = "0.13.0-pre.5"` --- elliptic-curve/Cargo.lock | 2 +- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/Cargo.lock b/elliptic-curve/Cargo.lock index 827b3abe9..000f440df 100644 --- a/elliptic-curve/Cargo.lock +++ b/elliptic-curve/Cargo.lock @@ -102,7 +102,7 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.6" +version = "0.13.0-pre.5" dependencies = [ "base16ct", "base64ct", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index c6cc181fa..fad2e2746 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "elliptic-curve" -version = "0.13.6" +version = "0.13.0-pre.5" description = """ General purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic curve forms, scalars, points, From a35e9f099bb730e861f70b09affa59335a0b1cc7 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 14:57:58 +0200 Subject: [PATCH 09/39] revert --- elliptic-curve/Cargo.lock | 2 +- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/Cargo.lock b/elliptic-curve/Cargo.lock index 000f440df..827b3abe9 100644 --- a/elliptic-curve/Cargo.lock +++ b/elliptic-curve/Cargo.lock @@ -102,7 +102,7 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.0-pre.5" +version = "0.13.6" dependencies = [ "base16ct", "base64ct", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index fad2e2746..c6cc181fa 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "elliptic-curve" -version = "0.13.0-pre.5" +version = "0.13.6" description = """ General purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic curve forms, scalars, points, From 8b120bcb5094f1a00b8cd5762ec998626af30543 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 17:11:25 +0200 Subject: [PATCH 10/39] expose ToAffineBatch --- elliptic-curve/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index 5f2a6c62e..4bea818f8 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -128,7 +128,7 @@ pub use zeroize; #[cfg(feature = "arithmetic")] pub use { crate::{ - arithmetic::{CurveArithmetic, PrimeCurveArithmetic}, + arithmetic::{CurveArithmetic, PrimeCurveArithmetic, ToAffineBatch}, point::{AffinePoint, ProjectivePoint}, public_key::PublicKey, scalar::{NonZeroScalar, Scalar}, From 2ac2bf4390de1b54a68ab267656a827eddbd9321 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 17:44:48 +0200 Subject: [PATCH 11/39] Refactor name --- elliptic-curve/src/arithmetic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 87735d126..02ea0a90f 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -87,13 +87,13 @@ pub trait PrimeCurveArithmetic: pub trait ToAffineBatch: CurveArithmetic { /// Converts a batch of points in their projective representation into the affine ones. - fn batch_to_affine_generic( + fn to_affine_batch_generic( points: [Self::ProjectivePoint; N], ) -> [Self::AffinePoint; N]; /// Converts a batch of points in their projective representation into the affine ones. #[cfg(feature = "alloc")] - fn batch_to_affine>( + fn to_affine_batch>( points: alloc::vec::Vec, ) -> B; } From caa8f04c56dacb86055338de5567fcdde37d097e Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 17:47:29 +0200 Subject: [PATCH 12/39] Take ref --- elliptic-curve/src/arithmetic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 02ea0a90f..51034dbd4 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -88,7 +88,7 @@ pub trait PrimeCurveArithmetic: pub trait ToAffineBatch: CurveArithmetic { /// Converts a batch of points in their projective representation into the affine ones. fn to_affine_batch_generic( - points: [Self::ProjectivePoint; N], + points: &[Self::ProjectivePoint; N], ) -> [Self::AffinePoint; N]; /// Converts a batch of points in their projective representation into the affine ones. From 99bc02c58a6f1297b15849fbfc59bbff0c853b5f Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 17:49:40 +0200 Subject: [PATCH 13/39] Take slice --- elliptic-curve/src/arithmetic.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 51034dbd4..75a5144e7 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -93,7 +93,5 @@ pub trait ToAffineBatch: CurveArithmetic { /// Converts a batch of points in their projective representation into the affine ones. #[cfg(feature = "alloc")] - fn to_affine_batch>( - points: alloc::vec::Vec, - ) -> B; + fn to_affine_batch>(points: &[Self::ProjectivePoint]) -> B; } From 71bf94ccf269cafc0446e220530e18f8388948ea Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 17:53:36 +0200 Subject: [PATCH 14/39] rename --- elliptic-curve/src/ops.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index fe3d66f17..56b977b00 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -50,7 +50,7 @@ impl< let mut field_elements_multiples_inverses = [field_elements[0]; N]; let mut field_elements_inverses = [field_elements[0]; N]; - let inversion_succeeded = invert_helper( + let inversion_succeeded = invert_batch_internal( field_elements, &mut field_elements_multiples, &mut field_elements_multiples_inverses, @@ -73,7 +73,7 @@ impl< .map(|i| field_elements[i]) .collect(); - let inversion_succeeded = invert_helper( + let inversion_succeeded = invert_batch_internal( field_elements, field_elements_multiples.as_mut(), field_elements_multiples_inverses.as_mut(), @@ -93,7 +93,7 @@ impl< /// to computing a single inversion, plus some storage and `O(n)` extra multiplications. /// /// See: https://iacr.org/archive/pkc2004/29470042/29470042.pdf section 2.2. -fn invert_helper< +fn invert_batch_internal< T: Invert> + Mul + Default + ConditionallySelectable, >( field_elements: &[T], From 6d80ad8deae799ffdebafb60fd910669e54b2cf3 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 18:11:34 +0200 Subject: [PATCH 15/39] doc --- elliptic-curve/src/arithmetic.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 75a5144e7..372c2d380 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -85,6 +85,9 @@ pub trait PrimeCurveArithmetic: type CurveGroup: group::prime::PrimeCurve::AffinePoint>; } +/// Perform a batched conversion to affine representation on a sequence of projective points +/// at an amortized cost that should be practically as efficient as a single conversion. +/// Internally, implementors should rely upon `InvertBatch`. pub trait ToAffineBatch: CurveArithmetic { /// Converts a batch of points in their projective representation into the affine ones. fn to_affine_batch_generic( From 8133e505ee8a49c12854acef529d5ec2c9b6debd Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 12 Nov 2023 23:55:26 +0200 Subject: [PATCH 16/39] Update elliptic-curve/src/ops.rs Co-authored-by: Tony Arcieri --- elliptic-curve/src/ops.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 56b977b00..f0b03b6db 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -37,13 +37,13 @@ pub trait InvertBatch: Invert + Sized { fn invert_batch>(field_elements: &[Self]) -> CtOption; } -impl< - T: Invert> - + Mul - + Copy - + Default - + ConditionallySelectable, - > InvertBatch for T +impl InvertBatch for T +where + T: Invert> + + Mul + + Copy + + Default + + ConditionallySelectable, { fn invert_batch_generic(field_elements: &[Self; N]) -> CtOption<[Self; N]> { let mut field_elements_multiples = [field_elements[0]; N]; From 505af723791e588de0627a079e301b05c7766ade Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 00:05:58 +0200 Subject: [PATCH 17/39] CR --- elliptic-curve/src/ops.rs | 100 ++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 54 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 56b977b00..23330fd84 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -28,63 +28,55 @@ pub trait Invert { /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) /// at an amortized cost that should be practically as efficient as a single inversion. -pub trait InvertBatch: Invert + Sized { - /// Invert a batch of field elements. - fn invert_batch_generic(field_elements: &[Self; N]) -> CtOption<[Self; N]>; - - /// Invert a batch of field elements. - #[cfg(feature = "alloc")] - fn invert_batch>(field_elements: &[Self]) -> CtOption; +/// This variation takes a const-generic array and thus does not require `alloc`. +pub fn invert_batch_array(field_elements: &[T; N]) -> CtOption<[T; N]> +where + T: Invert> + Mul + Copy + Default + ConditionallySelectable, +{ + let mut field_elements_multiples = [field_elements[0]; N]; + let mut field_elements_multiples_inverses = [field_elements[0]; N]; + let mut field_elements_inverses = [field_elements[0]; N]; + + let inversion_succeeded = invert_batch_internal( + field_elements, + &mut field_elements_multiples, + &mut field_elements_multiples_inverses, + &mut field_elements_inverses, + ); + + CtOption::new(field_elements_inverses, inversion_succeeded) } -impl< - T: Invert> - + Mul - + Copy - + Default - + ConditionallySelectable, - > InvertBatch for T +/// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) +/// at an amortized cost that should be practically as efficient as a single inversion. +/// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). +/// However, this also requires to make dynamic allocations and as such requires `alloc`. +#[cfg(feature = "alloc")] +pub fn invert_batch_slice, T>(field_elements: &[T]) -> CtOption +where + T: Invert> + Mul + Copy + Default + ConditionallySelectable, { - fn invert_batch_generic(field_elements: &[Self; N]) -> CtOption<[Self; N]> { - let mut field_elements_multiples = [field_elements[0]; N]; - let mut field_elements_multiples_inverses = [field_elements[0]; N]; - let mut field_elements_inverses = [field_elements[0]; N]; - - let inversion_succeeded = invert_batch_internal( - field_elements, - &mut field_elements_multiples, - &mut field_elements_multiples_inverses, - &mut field_elements_inverses, - ); - - CtOption::new(field_elements_inverses, inversion_succeeded) - } - - #[cfg(feature = "alloc")] - fn invert_batch>(field_elements: &[Self]) -> CtOption { - let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()) - .map(|i| field_elements[i]) - .collect(); - let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements - .len()) - .map(|i| field_elements[i]) - .collect(); - let mut field_elements_inverses: alloc::vec::Vec = (0..field_elements.len()) - .map(|i| field_elements[i]) - .collect(); - - let inversion_succeeded = invert_batch_internal( - field_elements, - field_elements_multiples.as_mut(), - field_elements_multiples_inverses.as_mut(), - field_elements_inverses.as_mut(), - ); - - CtOption::new( - field_elements_inverses.into_iter().collect(), - inversion_succeeded, - ) - } + let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()) + .map(|i| field_elements[i]) + .collect(); + let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements.len()) + .map(|i| field_elements[i]) + .collect(); + let mut field_elements_inverses: alloc::vec::Vec = (0..field_elements.len()) + .map(|i| field_elements[i]) + .collect(); + + let inversion_succeeded = invert_batch_internal( + field_elements, + field_elements_multiples.as_mut(), + field_elements_multiples_inverses.as_mut(), + field_elements_inverses.as_mut(), + ); + + CtOption::new( + field_elements_inverses.into_iter().collect(), + inversion_succeeded, + ) } /// Implements "Montgomery's trick", a trick for computing many modular inverses at once. From 5a4dff843764600c76be22a25ba7f0f8e13d0d37 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 00:11:32 +0200 Subject: [PATCH 18/39] Provided functions in `Invert` --- elliptic-curve/src/ops.rs | 111 ++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 23330fd84..1ef482cd0 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -24,59 +24,68 @@ pub trait Invert { // Fall back on constant-time implementation by default. self.invert() } -} -/// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) -/// at an amortized cost that should be practically as efficient as a single inversion. -/// This variation takes a const-generic array and thus does not require `alloc`. -pub fn invert_batch_array(field_elements: &[T; N]) -> CtOption<[T; N]> -where - T: Invert> + Mul + Copy + Default + ConditionallySelectable, -{ - let mut field_elements_multiples = [field_elements[0]; N]; - let mut field_elements_multiples_inverses = [field_elements[0]; N]; - let mut field_elements_inverses = [field_elements[0]; N]; - - let inversion_succeeded = invert_batch_internal( - field_elements, - &mut field_elements_multiples, - &mut field_elements_multiples_inverses, - &mut field_elements_inverses, - ); - - CtOption::new(field_elements_inverses, inversion_succeeded) -} + /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) + /// at an amortized cost that should be practically as efficient as a single inversion. + /// This variation takes a const-generic array and thus does not require `alloc`. + fn invert_batch_array(field_elements: &[Self; N]) -> CtOption<[Self; N]> + where + Self: Invert> + + Mul + + Copy + + Default + + ConditionallySelectable, + { + let mut field_elements_multiples = [field_elements[0]; N]; + let mut field_elements_multiples_inverses = [field_elements[0]; N]; + let mut field_elements_inverses = [field_elements[0]; N]; + + let inversion_succeeded = invert_batch_internal( + field_elements, + &mut field_elements_multiples, + &mut field_elements_multiples_inverses, + &mut field_elements_inverses, + ); + + CtOption::new(field_elements_inverses, inversion_succeeded) + } -/// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) -/// at an amortized cost that should be practically as efficient as a single inversion. -/// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). -/// However, this also requires to make dynamic allocations and as such requires `alloc`. -#[cfg(feature = "alloc")] -pub fn invert_batch_slice, T>(field_elements: &[T]) -> CtOption -where - T: Invert> + Mul + Copy + Default + ConditionallySelectable, -{ - let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()) - .map(|i| field_elements[i]) - .collect(); - let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements.len()) - .map(|i| field_elements[i]) - .collect(); - let mut field_elements_inverses: alloc::vec::Vec = (0..field_elements.len()) - .map(|i| field_elements[i]) - .collect(); - - let inversion_succeeded = invert_batch_internal( - field_elements, - field_elements_multiples.as_mut(), - field_elements_multiples_inverses.as_mut(), - field_elements_inverses.as_mut(), - ); - - CtOption::new( - field_elements_inverses.into_iter().collect(), - inversion_succeeded, - ) + /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) + /// at an amortized cost that should be practically as efficient as a single inversion. + /// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). + /// However, this also requires to make dynamic allocations and as such requires `alloc`. + #[cfg(feature = "alloc")] + fn invert_batch_slice>(field_elements: &[Self]) -> CtOption + where + Self: Invert> + + Mul + + Copy + + Default + + ConditionallySelectable, + { + let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()) + .map(|i| field_elements[i]) + .collect(); + let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements + .len()) + .map(|i| field_elements[i]) + .collect(); + let mut field_elements_inverses: alloc::vec::Vec = (0..field_elements.len()) + .map(|i| field_elements[i]) + .collect(); + + let inversion_succeeded = invert_batch_internal( + field_elements, + field_elements_multiples.as_mut(), + field_elements_multiples_inverses.as_mut(), + field_elements_inverses.as_mut(), + ); + + CtOption::new( + field_elements_inverses.into_iter().collect(), + inversion_succeeded, + ) + } } /// Implements "Montgomery's trick", a trick for computing many modular inverses at once. From 62521a9b6d0ce0a21b3a8e080cf71a08128c72fa Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 00:16:52 +0200 Subject: [PATCH 19/39] Refactored `ToAffineBatch` --- elliptic-curve/src/arithmetic.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 372c2d380..ae0302f88 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -90,11 +90,15 @@ pub trait PrimeCurveArithmetic: /// Internally, implementors should rely upon `InvertBatch`. pub trait ToAffineBatch: CurveArithmetic { /// Converts a batch of points in their projective representation into the affine ones. - fn to_affine_batch_generic( + /// /// This variation takes a const-generic array and thus does not require `alloc`. + fn to_affine_batch_array( points: &[Self::ProjectivePoint; N], ) -> [Self::AffinePoint; N]; /// Converts a batch of points in their projective representation into the affine ones. + /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn to_affine_batch>(points: &[Self::ProjectivePoint]) -> B; + fn to_affine_batch_slice>( + points: &[Self::ProjectivePoint], + ) -> B; } From 91dea565904fb5a20439bb326c023fbe29693aeb Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 10:09:57 +0200 Subject: [PATCH 20/39] CR --- elliptic-curve/src/arithmetic.rs | 24 +++++++++++++----------- elliptic-curve/src/lib.rs | 2 +- elliptic-curve/src/ops.rs | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index ae0302f88..5b781ccc8 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -85,20 +85,22 @@ pub trait PrimeCurveArithmetic: type CurveGroup: group::prime::PrimeCurve::AffinePoint>; } -/// Perform a batched conversion to affine representation on a sequence of projective points -/// at an amortized cost that should be practically as efficient as a single conversion. -/// Internally, implementors should rely upon `InvertBatch`. -pub trait ToAffineBatch: CurveArithmetic { - /// Converts a batch of points in their projective representation into the affine ones. - /// /// This variation takes a const-generic array and thus does not require `alloc`. - fn to_affine_batch_array( +/// Normalize point(s) in projective representation by converting them to their affine ones. +pub trait Normalize: CurveArithmetic { + /// Perform a batched conversion to affine representation on a sequence of projective points + /// at an amortized cost that should be practically as efficient as a single conversion. + /// Internally, implementors should rely upon `InvertBatch`. + /// This variation takes a const-generic array and thus does not require `alloc`. + fn batch_normalize_array( points: &[Self::ProjectivePoint; N], ) -> [Self::AffinePoint; N]; - /// Converts a batch of points in their projective representation into the affine ones. + /// Perform a batched conversion to affine representation on a sequence of projective points + /// at an amortized cost that should be practically as efficient as a single conversion. + /// Internally, implementors should rely upon `InvertBatch`. + /// This variation takes a (possibly dynamically allocated) slice and returns `FromIterator` + /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn to_affine_batch_slice>( - points: &[Self::ProjectivePoint], - ) -> B; + fn batch_normalize>(points: &[Self::ProjectivePoint]) -> B; } diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index 4bea818f8..ff870eb5a 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -128,7 +128,7 @@ pub use zeroize; #[cfg(feature = "arithmetic")] pub use { crate::{ - arithmetic::{CurveArithmetic, PrimeCurveArithmetic, ToAffineBatch}, + arithmetic::{CurveArithmetic, Normalize, PrimeCurveArithmetic}, point::{AffinePoint, ProjectivePoint}, public_key::PublicKey, scalar::{NonZeroScalar, Scalar}, diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 1ef482cd0..bdbd92678 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -28,7 +28,7 @@ pub trait Invert { /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) /// at an amortized cost that should be practically as efficient as a single inversion. /// This variation takes a const-generic array and thus does not require `alloc`. - fn invert_batch_array(field_elements: &[Self; N]) -> CtOption<[Self; N]> + fn batch_invert_array(field_elements: &[Self; N]) -> CtOption<[Self; N]> where Self: Invert> + Mul @@ -55,7 +55,7 @@ pub trait Invert { /// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn invert_batch_slice>(field_elements: &[Self]) -> CtOption + fn batch_invert>(field_elements: &[Self]) -> CtOption where Self: Invert> + Mul From 8ec02ee9d3bd0fdfcc490369a4fe895077301314 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 10:22:43 +0200 Subject: [PATCH 21/39] Refactor `Normalize` --- elliptic-curve/src/arithmetic.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 5b781ccc8..5e586203d 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -86,21 +86,22 @@ pub trait PrimeCurveArithmetic: } /// Normalize point(s) in projective representation by converting them to their affine ones. -pub trait Normalize: CurveArithmetic { +pub trait Normalize: Sized { + /// Converts the point to its affine representation. + fn to_affine(&self) -> AffinePoint; + /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. /// This variation takes a const-generic array and thus does not require `alloc`. - fn batch_normalize_array( - points: &[Self::ProjectivePoint; N], - ) -> [Self::AffinePoint; N]; + fn batch_normalize_array(points: &[Self; N]) -> [AffinePoint; N]; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. - /// This variation takes a (possibly dynamically allocated) slice and returns `FromIterator` + /// This variation takes a (possibly dynamically allocated) slice and returns `FromIterator` /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_normalize>(points: &[Self::ProjectivePoint]) -> B; + fn batch_normalize>(points: &[Self]) -> B; } From aa1b462c5a6f6e30e0523a8ae80704bb5324d287 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 10:26:41 +0200 Subject: [PATCH 22/39] Added `to_affine` --- elliptic-curve/src/arithmetic.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 5e586203d..4c7ec6491 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -86,22 +86,25 @@ pub trait PrimeCurveArithmetic: } /// Normalize point(s) in projective representation by converting them to their affine ones. -pub trait Normalize: Sized { +pub trait Normalize: Sized { + /// Elliptic curve point in affine coordinates. + type AffinePoint; + /// Converts the point to its affine representation. - fn to_affine(&self) -> AffinePoint; + fn to_affine(&self) -> Self::AffinePoint; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. /// This variation takes a const-generic array and thus does not require `alloc`. - fn batch_normalize_array(points: &[Self; N]) -> [AffinePoint; N]; + fn batch_normalize_array(points: &[Self; N]) -> [Self::AffinePoint; N]; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. - /// This variation takes a (possibly dynamically allocated) slice and returns `FromIterator` + /// This variation takes a (possibly dynamically allocated) slice and returns `FromIterator` /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_normalize>(points: &[Self]) -> B; + fn batch_normalize>(points: &[Self]) -> B; } From f6eca00c2cd25ec6587d766cba8353a090fd1f7b Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 20:24:57 +0200 Subject: [PATCH 23/39] condition on `Curve` --- elliptic-curve/src/arithmetic.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 4c7ec6491..708c1d14f 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -86,18 +86,12 @@ pub trait PrimeCurveArithmetic: } /// Normalize point(s) in projective representation by converting them to their affine ones. -pub trait Normalize: Sized { - /// Elliptic curve point in affine coordinates. - type AffinePoint; - - /// Converts the point to its affine representation. - fn to_affine(&self) -> Self::AffinePoint; - +pub trait Normalize: group::Curve { /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. /// This variation takes a const-generic array and thus does not require `alloc`. - fn batch_normalize_array(points: &[Self; N]) -> [Self::AffinePoint; N]; + fn batch_normalize_array(points: &[Self; N]) -> [Self::AffineRepr; N]; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. @@ -106,5 +100,5 @@ pub trait Normalize: Sized { /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_normalize>(points: &[Self]) -> B; + fn batch_normalize>(points: &[Self]) -> B; } From 822a1ba8b67e8c4edef1c16506363243b3da061d Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 13 Nov 2023 20:28:01 +0200 Subject: [PATCH 24/39] rename --- elliptic-curve/src/arithmetic.rs | 2 +- elliptic-curve/src/ops.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 708c1d14f..d1c873b7e 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -100,5 +100,5 @@ pub trait Normalize: group::Curve { /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_normalize>(points: &[Self]) -> B; + fn batch_normalize_slice>(points: &[Self]) -> B; } diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index bdbd92678..77420db68 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -55,7 +55,7 @@ pub trait Invert { /// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_invert>(field_elements: &[Self]) -> CtOption + fn batch_invert_slice>(field_elements: &[Self]) -> CtOption where Self: Invert> + Mul From f536c74ed09c5939cf73acd5350dec45988b9a3c Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 01:01:07 +0200 Subject: [PATCH 25/39] change to `vec` --- elliptic-curve/src/arithmetic.rs | 2 +- elliptic-curve/src/ops.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index d1c873b7e..03c3ae13a 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -100,5 +100,5 @@ pub trait Normalize: group::Curve { /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_normalize_slice>(points: &[Self]) -> B; + fn batch_normalize_vec(points: alloc::vec::Vec) -> alloc::vec::Vec; } diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 77420db68..ce56de144 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -55,7 +55,7 @@ pub trait Invert { /// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_invert_slice>(field_elements: &[Self]) -> CtOption + fn batch_invert_vec(field_elements: alloc::vec::Vec) -> CtOption> where Self: Invert> + Mul @@ -75,7 +75,7 @@ pub trait Invert { .collect(); let inversion_succeeded = invert_batch_internal( - field_elements, + &field_elements, field_elements_multiples.as_mut(), field_elements_multiples_inverses.as_mut(), field_elements_inverses.as_mut(), From 51b9703d713c6085167371ec9c2ed3206d967885 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 10:45:32 +0200 Subject: [PATCH 26/39] CR --- elliptic-curve/src/arithmetic.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 03c3ae13a..414024e78 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -100,5 +100,12 @@ pub trait Normalize: group::Curve { /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_normalize_vec(points: alloc::vec::Vec) -> alloc::vec::Vec; + fn batch_normalize_to_vec(points: &[Self]) -> alloc::vec::Vec + where + Self::AffineRepr: Copy + Default, + { + let mut ret = vec![Self::AffineRepr::default(); points.len()]; + Self::batch_normalize(points, &mut ret); + ret + } } From 2d8eb47ef3de42898aec647a7e2b89eec10ce2a4 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 10:49:39 +0200 Subject: [PATCH 27/39] rename --- elliptic-curve/src/ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index ce56de144..66473f8a8 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -55,7 +55,7 @@ pub trait Invert { /// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_invert_vec(field_elements: alloc::vec::Vec) -> CtOption> + fn batch_invert_to_vec(field_elements: &[Self]) -> CtOption> where Self: Invert> + Mul From 0e90c0beb5d1b3f2827caaa420f445a40fb0e708 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 10:53:18 +0200 Subject: [PATCH 28/39] clippy --- elliptic-curve/src/ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 66473f8a8..c71f935c5 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -75,7 +75,7 @@ pub trait Invert { .collect(); let inversion_succeeded = invert_batch_internal( - &field_elements, + field_elements, field_elements_multiples.as_mut(), field_elements_multiples_inverses.as_mut(), field_elements_inverses.as_mut(), From 719afbb10da35e485b6072992ea5a18237a0ccac Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 22:28:04 +0200 Subject: [PATCH 29/39] CR --- elliptic-curve/src/arithmetic.rs | 5 ++++- elliptic-curve/src/ops.rs | 25 +++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 414024e78..e2f6465e6 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -10,6 +10,9 @@ use core::fmt::Debug; use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption}; use zeroize::DefaultIsZeroes; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + /// Elliptic curve with an arithmetic implementation. pub trait CurveArithmetic: Curve { /// Elliptic curve point in affine coordinates. @@ -100,7 +103,7 @@ pub trait Normalize: group::Curve { /// allowing it to work with any container. /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_normalize_to_vec(points: &[Self]) -> alloc::vec::Vec + fn batch_normalize_to_vec(points: &[Self]) -> Vec where Self::AffineRepr: Copy + Default, { diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index c71f935c5..b2ba4f9df 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -6,6 +6,9 @@ use crypto_bigint::Integer; use group::Group; use subtle::{Choice, ConditionallySelectable, CtOption}; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + /// Perform an inversion on a field element (i.e. base field element or scalar) pub trait Invert { /// Field element type @@ -36,9 +39,9 @@ pub trait Invert { + Default + ConditionallySelectable, { - let mut field_elements_multiples = [field_elements[0]; N]; - let mut field_elements_multiples_inverses = [field_elements[0]; N]; - let mut field_elements_inverses = [field_elements[0]; N]; + let mut field_elements_multiples = [Self::default(); N]; + let mut field_elements_multiples_inverses = [Self::default(); N]; + let mut field_elements_inverses = [Self::default(); N]; let inversion_succeeded = invert_batch_internal( field_elements, @@ -55,7 +58,7 @@ pub trait Invert { /// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). /// However, this also requires to make dynamic allocations and as such requires `alloc`. #[cfg(feature = "alloc")] - fn batch_invert_to_vec(field_elements: &[Self]) -> CtOption> + fn batch_invert_to_vec(field_elements: &[Self]) -> CtOption> where Self: Invert> + Mul @@ -63,16 +66,10 @@ pub trait Invert { + Default + ConditionallySelectable, { - let mut field_elements_multiples: alloc::vec::Vec = (0..field_elements.len()) - .map(|i| field_elements[i]) - .collect(); - let mut field_elements_multiples_inverses: alloc::vec::Vec = (0..field_elements - .len()) - .map(|i| field_elements[i]) - .collect(); - let mut field_elements_inverses: alloc::vec::Vec = (0..field_elements.len()) - .map(|i| field_elements[i]) - .collect(); + let mut field_elements_multiples: Vec = vec![Self::default(); field_elements.len()]; + let mut field_elements_multiples_inverses: Vec = + vec![Self::default(); field_elements.len()]; + let mut field_elements_inverses: Vec = vec![Self::default(); field_elements.len()]; let inversion_succeeded = invert_batch_internal( field_elements, From ef22c20a8bb4b72e35d064dbc1731bb278921cad Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 23:33:43 +0200 Subject: [PATCH 30/39] Refactored trait --- elliptic-curve/src/arithmetic.rs | 24 ++----------- elliptic-curve/src/ops.rs | 58 +++++++++++++++++++------------- 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index e2f6465e6..1e1c27f6c 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -10,9 +10,6 @@ use core::fmt::Debug; use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption}; use zeroize::DefaultIsZeroes; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; - /// Elliptic curve with an arithmetic implementation. pub trait CurveArithmetic: Curve { /// Elliptic curve point in affine coordinates. @@ -89,26 +86,11 @@ pub trait PrimeCurveArithmetic: } /// Normalize point(s) in projective representation by converting them to their affine ones. -pub trait Normalize: group::Curve { - /// Perform a batched conversion to affine representation on a sequence of projective points - /// at an amortized cost that should be practically as efficient as a single conversion. - /// Internally, implementors should rely upon `InvertBatch`. - /// This variation takes a const-generic array and thus does not require `alloc`. - fn batch_normalize_array(points: &[Self; N]) -> [Self::AffineRepr; N]; +pub trait Normalize: group::Curve { + type Output: AsRef; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. - /// This variation takes a (possibly dynamically allocated) slice and returns `FromIterator` - /// allowing it to work with any container. - /// However, this also requires to make dynamic allocations and as such requires `alloc`. - #[cfg(feature = "alloc")] - fn batch_normalize_to_vec(points: &[Self]) -> Vec - where - Self::AffineRepr: Copy + Default, - { - let mut ret = vec![Self::AffineRepr::default(); points.len()]; - Self::batch_normalize(points, &mut ret); - ret - } + fn batch_normalize(points: &Points) -> >::Output; } diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index b2ba4f9df..401a09de3 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -27,18 +27,28 @@ pub trait Invert { // Fall back on constant-time implementation by default. self.invert() } +} - /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) - /// at an amortized cost that should be practically as efficient as a single inversion. - /// This variation takes a const-generic array and thus does not require `alloc`. - fn batch_invert_array(field_elements: &[Self; N]) -> CtOption<[Self; N]> - where - Self: Invert> - + Mul - + Copy - + Default - + ConditionallySelectable, - { +/// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) +/// at an amortized cost that should be practically as efficient as a single inversion. +pub trait BatchInvert: Invert { + type Output; + + /// Invert a batch of field elements. + fn batch_invert(field_elements: FieldElements) -> >::Output; +} + +impl BatchInvert<&[T; N]> for T +where + T: Invert> + + Mul + + Copy + + Default + + ConditionallySelectable, +{ + type Output = CtOption<[Self; N]>; + + fn batch_invert(field_elements: &[Self; N]) -> >::Output { let mut field_elements_multiples = [Self::default(); N]; let mut field_elements_multiples_inverses = [Self::default(); N]; let mut field_elements_inverses = [Self::default(); N]; @@ -52,20 +62,20 @@ pub trait Invert { CtOption::new(field_elements_inverses, inversion_succeeded) } +} - /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) - /// at an amortized cost that should be practically as efficient as a single inversion. - /// This variation takes a (possibly dynamically allocated) sequence and returns `FromIterator`, which allows it to work with any container (e.g. `Vec<_>`). - /// However, this also requires to make dynamic allocations and as such requires `alloc`. - #[cfg(feature = "alloc")] - fn batch_invert_to_vec(field_elements: &[Self]) -> CtOption> - where - Self: Invert> - + Mul - + Copy - + Default - + ConditionallySelectable, - { +#[cfg(feature = "alloc")] +impl BatchInvert<&[T]> for T +where + T: Invert> + + Mul + + Copy + + Default + + ConditionallySelectable, +{ + type Output = CtOption>; + + fn batch_invert(field_elements: &[Self]) -> >::Output { let mut field_elements_multiples: Vec = vec![Self::default(); field_elements.len()]; let mut field_elements_multiples_inverses: Vec = vec![Self::default(); field_elements.len()]; From e557e013ee0d487a7497962fcc2877c6ec93d6dd Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 23:38:38 +0200 Subject: [PATCH 31/39] Missing doc --- elliptic-curve/src/arithmetic.rs | 1 + elliptic-curve/src/ops.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 1e1c27f6c..b62048156 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -87,6 +87,7 @@ pub trait PrimeCurveArithmetic: /// Normalize point(s) in projective representation by converting them to their affine ones. pub trait Normalize: group::Curve { + /// The output of the batch normalization; a container of affine points. type Output: AsRef; /// Perform a batched conversion to affine representation on a sequence of projective points diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 401a09de3..74816671c 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -73,6 +73,7 @@ where + Default + ConditionallySelectable, { + /// The output of batch inversion. A container of field elements. type Output = CtOption>; fn batch_invert(field_elements: &[Self]) -> >::Output { From 2555db14d5d5ce88fec379ade62103c640bb4e6f Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 23:40:45 +0200 Subject: [PATCH 32/39] Missing doc oops --- elliptic-curve/src/ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 74816671c..5edddc4ee 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -32,6 +32,7 @@ pub trait Invert { /// Perform a batched inversion on a sequence of field elements (i.e. base field elements or scalars) /// at an amortized cost that should be practically as efficient as a single inversion. pub trait BatchInvert: Invert { + /// The output of batch inversion. A container of field elements. type Output; /// Invert a batch of field elements. @@ -73,7 +74,6 @@ where + Default + ConditionallySelectable, { - /// The output of batch inversion. A container of field elements. type Output = CtOption>; fn batch_invert(field_elements: &[Self]) -> >::Output { From fe4d241343ac39a83c505470395d3ad44a1b59fd Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 23:47:40 +0200 Subject: [PATCH 33/39] Remove `AsRef` --- elliptic-curve/src/arithmetic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index b62048156..d41fbab38 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -88,7 +88,7 @@ pub trait PrimeCurveArithmetic: /// Normalize point(s) in projective representation by converting them to their affine ones. pub trait Normalize: group::Curve { /// The output of the batch normalization; a container of affine points. - type Output: AsRef; + type Output; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. From ec3669b4cb346bc058013c13d970691ecf4dcc7c Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 23:49:18 +0200 Subject: [PATCH 34/39] Remove const parameter from trait fn --- elliptic-curve/src/arithmetic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index d41fbab38..403a5281a 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -93,5 +93,5 @@ pub trait Normalize: group::Curve { /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. - fn batch_normalize(points: &Points) -> >::Output; + fn batch_normalize(points: &Points) -> >::Output; } From 0b9e030ee4ce429972a7083814420914915c763e Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 23:50:25 +0200 Subject: [PATCH 35/39] Remove reference from trait fn --- elliptic-curve/src/arithmetic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 403a5281a..7fc1225ec 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -93,5 +93,5 @@ pub trait Normalize: group::Curve { /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. - fn batch_normalize(points: &Points) -> >::Output; + fn batch_normalize(points: Points) -> >::Output; } From b3bdfb1dc5758cf8d46adfaaa0540685ab2ac11e Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Tue, 14 Nov 2023 23:58:59 +0200 Subject: [PATCH 36/39] Update elliptic-curve/src/arithmetic.rs Co-authored-by: Tony Arcieri --- elliptic-curve/src/arithmetic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 7fc1225ec..b99fd8cd4 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -86,7 +86,7 @@ pub trait PrimeCurveArithmetic: } /// Normalize point(s) in projective representation by converting them to their affine ones. -pub trait Normalize: group::Curve { +pub trait BatchNormalize: group::Curve { /// The output of the batch normalization; a container of affine points. type Output; From 0ced10a29196487085f96275e394efa0bf0e3ee3 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Wed, 15 Nov 2023 00:02:04 +0200 Subject: [PATCH 37/39] Trying as-ref again --- elliptic-curve/src/arithmetic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index b99fd8cd4..a7a8b28be 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -88,10 +88,10 @@ pub trait PrimeCurveArithmetic: /// Normalize point(s) in projective representation by converting them to their affine ones. pub trait BatchNormalize: group::Curve { /// The output of the batch normalization; a container of affine points. - type Output; + type Output: AsRef; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion. /// Internally, implementors should rely upon `InvertBatch`. - fn batch_normalize(points: Points) -> >::Output; + fn batch_normalize(points: Points) -> >::Output; } From dd7b7b6e8f17953ce9c067a6d2ffc66b4a040cf2 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Wed, 15 Nov 2023 00:05:01 +0200 Subject: [PATCH 38/39] compilation --- elliptic-curve/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index 4c6040e1b..389d9713d 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -127,7 +127,7 @@ pub use zeroize; #[cfg(feature = "arithmetic")] pub use { crate::{ - arithmetic::{CurveArithmetic, Normalize, PrimeCurveArithmetic}, + arithmetic::{BatchNormalize, CurveArithmetic, PrimeCurveArithmetic}, point::{AffinePoint, ProjectivePoint}, public_key::PublicKey, scalar::{NonZeroScalar, Scalar}, From 017fa2972f23b9e67bcbff2ccca2f1905b8f4aa3 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Wed, 15 Nov 2023 00:07:02 +0200 Subject: [PATCH 39/39] as-ref suggestion --- elliptic-curve/src/arithmetic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index a7a8b28be..de9ff6b3c 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -88,7 +88,7 @@ pub trait PrimeCurveArithmetic: /// Normalize point(s) in projective representation by converting them to their affine ones. pub trait BatchNormalize: group::Curve { /// The output of the batch normalization; a container of affine points. - type Output: AsRef; + type Output: AsRef<[Self::AffineRepr]>; /// Perform a batched conversion to affine representation on a sequence of projective points /// at an amortized cost that should be practically as efficient as a single conversion.