From b4e87492d7db6477c05b6e8a53b95c6d87406736 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 30 Dec 2022 10:05:11 -0700 Subject: [PATCH 01/22] Add `Group::mul_by_generator` Adds a provided method to the `Group` trait for performing multiplication by the generator. The use case is overriding this method in the event that precomputed scalar multiplication tables are available, which may be conditional depending on crate features like `alloc` or feature-gated static precomputed tables. --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 27ed5c9..b738244 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,12 @@ pub trait Group: /// Doubles this element. #[must_use] fn double(&self) -> Self; + + /// Multiply by the generator of the prime-order subgroup. + #[must_use] + fn mul_by_generator(scalar: &Self::Scalar) -> Self { + Self::generator() * scalar + } } /// Efficient representation of an elliptic curve point guaranteed. From 6ab641f6ac8bb0bfd1e72faa0a94a3b13166840a Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 16 Apr 2025 11:45:26 +0000 Subject: [PATCH 02/22] Raise MSRV to 1.63 --- CHANGELOG.md | 2 ++ Cargo.toml | 2 +- README.md | 2 +- rust-toolchain.toml | 2 +- src/wnaf.rs | 6 ++++++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aec3f6d..591a72e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- MSRV is now 1.63.0. ## [0.13.0] - 2022-12-06 ### Changed diff --git a/Cargo.toml b/Cargo.toml index bff1cf0..49fe2ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ "Jack Grigg ", ] edition = "2021" -rust-version = "1.56" +rust-version = "1.63" readme = "README.md" license = "MIT/Apache-2.0" diff --git a/README.md b/README.md index c3c0640..efff81c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ wider discussion. ## Minimum Supported Rust Version -Requires Rust **1.56** or higher. +Requires Rust **1.63** or higher. Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index de43b23..3eebdfe 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.56.0" +channel = "1.63.0" components = [ "clippy", "rustfmt" ] diff --git a/src/wnaf.rs b/src/wnaf.rs index 175d676..fdcf432 100644 --- a/src/wnaf.rs +++ b/src/wnaf.rs @@ -255,6 +255,12 @@ pub struct Wnaf { window_size: W, } +impl Default for Wnaf<(), Vec, Vec> { + fn default() -> Self { + Self::new() + } +} + impl Wnaf<(), Vec, Vec> { /// Construct a new wNAF context without allocating. pub fn new() -> Self { From 8240c176e346c20b6fa8bec87c4b88cd4bcc2faa Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 16 Apr 2025 11:49:01 +0000 Subject: [PATCH 03/22] Update lockfile to latest MSRV-compatible dependencies --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46af6c4..775e6a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "rand_core", "subtle", @@ -26,9 +26,9 @@ dependencies = [ [[package]] name = "memuse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a" +checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" [[package]] name = "rand" @@ -56,6 +56,6 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" From 055cc14b002b22bde892c07602561ca026f884e1 Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sun, 26 Jan 2025 08:59:10 +0000 Subject: [PATCH 04/22] Bump to rust-random 0.9 Co-authored-by: Jack Grigg --- CHANGELOG.md | 1 + Cargo.lock | 71 ++++++++++++++++++++++++++++++++++++++++++------ Cargo.toml | 9 ++++-- src/tests/mod.rs | 4 +-- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 591a72e..3276d5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Changed - MSRV is now 1.63.0. +- Migrated to `ff 0.14`, `rand_core 0.9`. ## [0.13.0] - 2022-12-06 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 775e6a1..c0263ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,8 +5,7 @@ version = 3 [[package]] name = "ff" version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +source = "git+https://github.com/zkcrypto/ff.git?rev=241caff9bcedafbe279b5a4d875461f66b3f9701#241caff9bcedafbe279b5a4d875461f66b3f9701" dependencies = [ "rand_core", "subtle", @@ -30,26 +29,45 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_core", + "zerocopy", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" [[package]] name = "rand_xorshift" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ "rand_core", ] @@ -59,3 +77,40 @@ name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "zerocopy" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 49fe2ba..b666707 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,9 @@ repository = "https://github.com/zkcrypto/group" [dependencies] ff = { version = "0.13", default-features = false } -rand = { version = "0.8", optional = true, default-features = false } -rand_core = { version = "0.6", default-features = false } -rand_xorshift = { version = "0.3", optional = true } +rand = { version = "0.9", optional = true, default-features = false } +rand_core = { version = "0.9", default-features = false } +rand_xorshift = { version = "0.4", optional = true } subtle = { version = "2.2.1", default-features = false } # Crate for exposing the dynamic memory usage of the w-NAF structs. @@ -33,3 +33,6 @@ wnaf-memuse = ["alloc", "memuse"] [badges] maintenance = { status = "actively-developed" } + +[patch.crates-io] +ff = { git = "https://github.com/zkcrypto/ff.git", rev = "241caff9bcedafbe279b5a4d875461f66b3f9701" } diff --git a/src/tests/mod.rs b/src/tests/mod.rs index ff79a9b..c81a926 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -378,8 +378,8 @@ fn random_transformation_tests() { for _ in 0..10 { let mut v = (0..1000).map(|_| G::random(&mut rng)).collect::>(); - use rand::distributions::{Distribution, Uniform}; - let between = Uniform::new(0, 1000); + use rand::distr::{Distribution, Uniform}; + let between = Uniform::new(0, 1000).unwrap(); // Sprinkle in some normalized points for _ in 0..5 { v[between.sample(&mut rng)] = G::identity(); From f3537bcd1c16a5ce48022e3eb948578fae4204c6 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Sun, 2 Mar 2025 21:37:03 -0800 Subject: [PATCH 05/22] Relax `Sized` requirements on the rng --- CHANGELOG.md | 3 +++ src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3276d5c..f8c7b05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ and this library adheres to Rust's notion of ### Changed - MSRV is now 1.63.0. - Migrated to `ff 0.14`, `rand_core 0.9`. +- `group::Group::random(rng: impl RngCore) -> Self` has been changed to + `Group::random(rng: &mut R) -> Self`, to enable passing a + trait object as the RNG. ## [0.13.0] - 2022-12-06 ### Changed diff --git a/src/lib.rs b/src/lib.rs index 27ed5c9..b59c590 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,7 @@ pub trait Group: /// this group. /// /// This function is non-deterministic, and samples from the user-provided RNG. - fn random(rng: impl RngCore) -> Self; + fn random(rng: &mut R) -> Self; /// Returns the additive identity, also known as the "neutral element". fn identity() -> Self; From 4456de88184251b95c98e089a74a5c107b494f14 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Sun, 2 Mar 2025 21:37:03 -0800 Subject: [PATCH 06/22] Provide a `Group::try_from_rng` --- CHANGELOG.md | 2 ++ src/lib.rs | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c7b05..d7434ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this library adheres to Rust's notion of - `group::Group::random(rng: impl RngCore) -> Self` has been changed to `Group::random(rng: &mut R) -> Self`, to enable passing a trait object as the RNG. +- `group::Group::try_from_rng` is a new trait method that must be implemented by + downstreams. `Group::random` now has a default implementation that calls it. ## [0.13.0] - 2022-12-06 ### Changed diff --git a/src/lib.rs b/src/lib.rs index b59c590..3116649 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,11 +9,12 @@ extern crate alloc; // Re-export ff to make version-matching easier. pub use ff; +use core::convert::Infallible; use core::fmt; use core::iter::Sum; use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use ff::PrimeField; -use rand_core::RngCore; +use rand_core::{RngCore, TryRngCore}; use subtle::{Choice, CtOption}; pub mod cofactor; @@ -76,7 +77,22 @@ pub trait Group: /// this group. /// /// This function is non-deterministic, and samples from the user-provided RNG. - fn random(rng: &mut R) -> Self; + fn random(rng: &mut R) -> Self { + Self::try_from_rng(rng) + .map_err(|e: Infallible| e) + .expect("Infallible failed") + + // NOTE: once MSRV gets to 1.82 remove the map_err/expect and use + // let Ok(out) = Self::try_from_rng(rng); + // out + // See: https://blog.rust-lang.org/2024/10/17/Rust-1.82.0.html#omitting-empty-types-in-pattern-matching + } + + /// Returns an element chosen uniformly at random from the non-identity elements of + /// this group. + /// + /// This function is non-deterministic, and samples from the user-provided RNG. + fn try_from_rng(rng: &mut R) -> Result; /// Returns the additive identity, also known as the "neutral element". fn identity() -> Self; From a2604792918e9a60c4ddf28d4572a0ac3378e968 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 17 Apr 2025 17:41:39 +0000 Subject: [PATCH 07/22] Preview 0.14.0-pre.0 --- Cargo.lock | 7 ++++--- Cargo.toml | 7 ++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0263ce..cffd341 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,8 +4,9 @@ version = 3 [[package]] name = "ff" -version = "0.13.1" -source = "git+https://github.com/zkcrypto/ff.git?rev=241caff9bcedafbe279b5a4d875461f66b3f9701#241caff9bcedafbe279b5a4d875461f66b3f9701" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d42dd26f5790eda47c1a2158ea4120e32c35ddc9a7743c98a292accc01b54ef3" dependencies = [ "rand_core", "subtle", @@ -13,7 +14,7 @@ dependencies = [ [[package]] name = "group" -version = "0.13.0" +version = "0.14.0-pre.0" dependencies = [ "ff", "memuse", diff --git a/Cargo.toml b/Cargo.toml index b666707..a153e74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "group" -version = "0.13.0" +version = "0.14.0-pre.0" authors = [ "Sean Bowe ", "Jack Grigg ", @@ -16,7 +16,7 @@ homepage = "https://github.com/zkcrypto/group" repository = "https://github.com/zkcrypto/group" [dependencies] -ff = { version = "0.13", default-features = false } +ff = { version = "=0.14.0-pre.0", default-features = false } rand = { version = "0.9", optional = true, default-features = false } rand_core = { version = "0.9", default-features = false } rand_xorshift = { version = "0.4", optional = true } @@ -33,6 +33,3 @@ wnaf-memuse = ["alloc", "memuse"] [badges] maintenance = { status = "actively-developed" } - -[patch.crates-io] -ff = { git = "https://github.com/zkcrypto/ff.git", rev = "241caff9bcedafbe279b5a4d875461f66b3f9701" } From 87fcee0f6c49d0420a32995ef62d6753b7f41d4e Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 1 Feb 2026 13:26:57 -0700 Subject: [PATCH 08/22] Bump `rand_core` to v0.10; MSRV 1.85 NOTE: depends on zkcrypto/ff#149 Release notes for `rand_core` v0.10.0: https://github.com/rust-random/rand_core/releases/tag/v0.10.0 --- .github/workflows/ci.yml | 3 +- Cargo.lock | 73 +++++----------------------------------- Cargo.toml | 11 +++--- rust-toolchain.toml | 2 +- src/lib.rs | 6 ++-- 5 files changed, 20 insertions(+), 75 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39f9e7b..6607146 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: strategy: matrix: target: - - wasm32-wasi + - wasm32-wasip1 - thumbv6m-none-eabi - thumbv7em-none-eabihf steps: @@ -81,7 +81,6 @@ jobs: - uses: actions/checkout@v4 - run: cargo fetch # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. - - run: sudo apt-get -y install libfontconfig1-dev - name: Check intra-doc links run: cargo doc --all-features --document-private-items diff --git a/Cargo.lock b/Cargo.lock index cffd341..f4a1376 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ff" version = "0.14.0-pre.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d42dd26f5790eda47c1a2158ea4120e32c35ddc9a7743c98a292accc01b54ef3" +source = "git+https://github.com/tarcieri/ff?branch=rand_core%2Fv0.10#810bfd0c67ee31663b696e6af26d1b2cea13c409" dependencies = [ "rand_core", "subtle", @@ -30,45 +29,26 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - [[package]] name = "rand" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ "rand_core", - "zerocopy", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" [[package]] name = "rand_xorshift" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +checksum = "60aa6af80be32871323012e02e6e65f8a7cc7890931ae421d217ad8fe0df2ccf" dependencies = [ "rand_core", ] @@ -78,40 +58,3 @@ name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml index a153e74..2cedce0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ "Jack Grigg ", ] edition = "2021" -rust-version = "1.63" +rust-version = "1.85" readme = "README.md" license = "MIT/Apache-2.0" @@ -17,9 +17,9 @@ repository = "https://github.com/zkcrypto/group" [dependencies] ff = { version = "=0.14.0-pre.0", default-features = false } -rand = { version = "0.9", optional = true, default-features = false } -rand_core = { version = "0.9", default-features = false } -rand_xorshift = { version = "0.4", optional = true } +rand = { version = "0.10", optional = true, default-features = false } +rand_core = { version = "0.10", default-features = false } +rand_xorshift = { version = "0.5", optional = true } subtle = { version = "2.2.1", default-features = false } # Crate for exposing the dynamic memory usage of the w-NAF structs. @@ -33,3 +33,6 @@ wnaf-memuse = ["alloc", "memuse"] [badges] maintenance = { status = "actively-developed" } + +[patch.crates-io] +ff = { git = "https://github.com/tarcieri/ff", branch = "rand_core/v0.10" } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 3eebdfe..efd3308 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.63.0" +channel = "1.85.0" components = [ "clippy", "rustfmt" ] diff --git a/src/lib.rs b/src/lib.rs index cd3cf5e..d0c9b10 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ use core::fmt; use core::iter::Sum; use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use ff::PrimeField; -use rand_core::{RngCore, TryRngCore}; +use rand_core::{Rng, TryRng}; use subtle::{Choice, CtOption}; pub mod cofactor; @@ -77,7 +77,7 @@ pub trait Group: /// this group. /// /// This function is non-deterministic, and samples from the user-provided RNG. - fn random(rng: &mut R) -> Self { + fn random(rng: &mut R) -> Self { Self::try_from_rng(rng) .map_err(|e: Infallible| e) .expect("Infallible failed") @@ -92,7 +92,7 @@ pub trait Group: /// this group. /// /// This function is non-deterministic, and samples from the user-provided RNG. - fn try_from_rng(rng: &mut R) -> Result; + fn try_from_rng(rng: &mut R) -> Result; /// Returns the additive identity, also known as the "neutral element". fn identity() -> Self; From 21104854da7f316c470213ab4a2ace239d24dd28 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 29 Jul 2023 17:32:01 +0000 Subject: [PATCH 09/22] Introduce `CurveAffine` trait This unifies the methods previously exposed by the `PrimeCurveAffine` and `CofactorCurveAffine` traits. The prime-order and cofactor traits are now all marker traits, and their affine-specific traits are automatically derived. --- CHANGELOG.md | 17 +++++++++++++++++ src/cofactor.rs | 48 ++++------------------------------------------- src/lib.rs | 49 +++++++++++++++++++++++++++++++++++++++++------- src/prime.rs | 44 ++++--------------------------------------- src/tests/mod.rs | 8 ++------ 5 files changed, 69 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7434ec..44138f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- `group::CurveAffine` + ### Changed - MSRV is now 1.63.0. - Migrated to `ff 0.14`, `rand_core 0.9`. @@ -14,6 +17,20 @@ and this library adheres to Rust's notion of trait object as the RNG. - `group::Group::try_from_rng` is a new trait method that must be implemented by downstreams. `Group::random` now has a default implementation that calls it. +- The curve-related traits have been refactored around the new `CurveAffine` + trait: + - `group::Curve::AffineRepr` has been renamed to `Curve::Affine`. + - All of the trait methods and associated types on the following traits have + been removed (use `group::Curve::Affine` or the `group::CurveAffine` trait + instead; trait implementors must implement `group::CurveAffine` instead + using the same logic): + - `group::cofactor::CofactorCurve` + - `group::cofactor::CofactorCurveAffine` + - `group::prime::PrimeCurve` + - `group::prime::PrimeCurveAffine` + - `group::cofactor::CofactorCurveAffine` and `group::prime::PrimeCurveAffine` + now have blanket implementations for all types `C: group::CurveAffine` where + `C::Curve` implements `CofactorCurve` or `PrimeCurve` respectively. ## [0.13.0] - 2022-12-06 ### Changed diff --git a/src/cofactor.rs b/src/cofactor.rs index 84bfe0a..fae0a89 100644 --- a/src/cofactor.rs +++ b/src/cofactor.rs @@ -1,9 +1,6 @@ -use core::fmt; -use core::ops::{Mul, Neg}; -use ff::PrimeField; use subtle::{Choice, CtOption}; -use crate::{prime::PrimeGroup, Curve, Group, GroupEncoding, GroupOps, GroupOpsOwned}; +use crate::{prime::PrimeGroup, Curve, CurveAffine, Group, GroupEncoding, GroupOps, GroupOpsOwned}; /// This trait represents an element of a cryptographic group with a large prime-order /// subgroup and a comparatively-small cofactor. @@ -54,47 +51,10 @@ pub trait CofactorGroup: /// Efficient representation of an elliptic curve point guaranteed to be /// in the correct prime order subgroup. -pub trait CofactorCurve: - Curve::Affine> + CofactorGroup -{ - type Affine: CofactorCurveAffine - + Mul - + for<'r> Mul<&'r Self::Scalar, Output = Self>; -} +pub trait CofactorCurve: Curve + CofactorGroup {} /// Affine representation of an elliptic curve point guaranteed to be /// in the correct prime order subgroup. -pub trait CofactorCurveAffine: - GroupEncoding - + Copy - + Clone - + Sized - + Send - + Sync - + fmt::Debug - + PartialEq - + Eq - + 'static - + Neg - + Mul<::Scalar, Output = ::Curve> - + for<'r> Mul< - &'r ::Scalar, - Output = ::Curve, - > -{ - type Scalar: PrimeField; - type Curve: CofactorCurve; - - /// Returns the additive identity. - fn identity() -> Self; +pub trait CofactorCurveAffine: CurveAffine {} - /// Returns a fixed generator of unknown exponent. - fn generator() -> Self; - - /// Determines if this point represents the point at infinity; the - /// additive identity. - fn is_identity(&self) -> Choice; - - /// Converts this element to its curve representation. - fn to_curve(&self) -> Self::Curve; -} +impl CofactorCurveAffine for C where C::Curve: CofactorCurve {} diff --git a/src/lib.rs b/src/lib.rs index cd3cf5e..4395525 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,16 +114,16 @@ pub trait Group: } } -/// Efficient representation of an elliptic curve point guaranteed. -pub trait Curve: - Group + GroupOps<::AffineRepr> + GroupOpsOwned<::AffineRepr> -{ +/// Efficient representation of an elliptic curve point. +pub trait Curve: Group + GroupOps + GroupOpsOwned { /// The affine representation for this elliptic curve. - type AffineRepr; + type Affine: CurveAffine + + Mul + + for<'r> Mul<&'r Self::Scalar, Output = Self>; /// Converts a batch of projective elements into affine elements. This function will /// panic if `p.len() != q.len()`. - fn batch_normalize(p: &[Self], q: &mut [Self::AffineRepr]) { + fn batch_normalize(p: &[Self], q: &mut [Self::Affine]) { assert_eq!(p.len(), q.len()); for (p, q) in p.iter().zip(q.iter_mut()) { @@ -132,7 +132,42 @@ pub trait Curve: } /// Converts this element into its affine representation. - fn to_affine(&self) -> Self::AffineRepr; + fn to_affine(&self) -> Self::Affine; +} + +/// Affine representation of an elliptic curve point. +pub trait CurveAffine: + GroupEncoding + + Copy + + fmt::Debug + + Eq + + Send + + Sync + + 'static + + Neg + + Mul<::Scalar, Output = Self::Curve> + + for<'r> Mul<&'r ::Scalar, Output = Self::Curve> +{ + /// The efficient representation for this elliptic curve. + type Curve: Curve; + + /// Scalars modulo the order of this group's scalar field. + /// + /// This associated type is temporary, and will be removed once downstream users have + /// migrated to using `Curve` as the primary generic bound. + type Scalar: PrimeField; + + /// Returns the additive identity. + fn identity() -> Self; + + /// Returns a fixed generator of unknown exponent. + fn generator() -> Self; + + /// Determines if this point represents the additive identity. + fn is_identity(&self) -> Choice; + + /// Converts this affine point to its efficient representation. + fn to_curve(&self) -> Self::Curve; } pub trait GroupEncoding: Sized { diff --git a/src/prime.rs b/src/prime.rs index 174888e..0964782 100644 --- a/src/prime.rs +++ b/src/prime.rs @@ -1,50 +1,14 @@ -use core::fmt; -use core::ops::{Mul, Neg}; -use ff::PrimeField; -use subtle::Choice; - -use crate::{Curve, Group, GroupEncoding}; +use crate::{Curve, CurveAffine, Group, GroupEncoding}; /// This trait represents an element of a prime-order cryptographic group. pub trait PrimeGroup: Group + GroupEncoding {} /// Efficient representation of an elliptic curve point guaranteed to be /// in the correct prime order subgroup. -pub trait PrimeCurve: Curve::Affine> + PrimeGroup { - type Affine: PrimeCurveAffine - + Mul - + for<'r> Mul<&'r Self::Scalar, Output = Self>; -} +pub trait PrimeCurve: Curve + PrimeGroup {} /// Affine representation of an elliptic curve point guaranteed to be /// in the correct prime order subgroup. -pub trait PrimeCurveAffine: GroupEncoding - + Copy - + Clone - + Sized - + Send - + Sync - + fmt::Debug - + PartialEq - + Eq - + 'static - + Neg - + Mul<::Scalar, Output = ::Curve> - + for<'r> Mul<&'r ::Scalar, Output = ::Curve> -{ - type Scalar: PrimeField; - type Curve: PrimeCurve; - - /// Returns the additive identity. - fn identity() -> Self; - - /// Returns a fixed generator of unknown exponent. - fn generator() -> Self; - - /// Determines if this point represents the point at infinity; the - /// additive identity. - fn is_identity(&self) -> Choice; +pub trait PrimeCurveAffine: CurveAffine {} - /// Converts this element to its curve representation. - fn to_curve(&self) -> Self::Curve; -} +impl PrimeCurveAffine for C where C::Curve: PrimeCurve {} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c81a926..a598e50 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -4,11 +4,7 @@ use ff::{Field, PrimeField}; use rand::SeedableRng; use rand_xorshift::XorShiftRng; -use crate::{ - prime::{PrimeCurve, PrimeCurveAffine}, - wnaf::WnafGroup, - GroupEncoding, UncompressedEncoding, -}; +use crate::{prime::PrimeCurve, wnaf::WnafGroup, CurveAffine, GroupEncoding, UncompressedEncoding}; pub fn curve_tests() { let mut rng = XorShiftRng::from_seed([ @@ -426,7 +422,7 @@ fn random_compressed_encoding_tests() { pub fn random_uncompressed_encoding_tests() where - ::Affine: UncompressedEncoding, + G::Affine: UncompressedEncoding, { let mut rng = XorShiftRng::from_seed([ 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, From 92f221bf647d0e782a38e707db411b1ee8f6534e Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 May 2026 14:51:42 -0600 Subject: [PATCH 10/22] Update patch to retarget ff 0.14.0 release branch --- Cargo.lock | 2 +- Cargo.toml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4a1376..ce53cf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ version = 4 [[package]] name = "ff" version = "0.14.0-pre.0" -source = "git+https://github.com/tarcieri/ff?branch=rand_core%2Fv0.10#810bfd0c67ee31663b696e6af26d1b2cea13c409" +source = "git+https://github.com/zkcrypto/ff?rev=bdd74a3f75c4c378d69e954944a61bb0930532a0#bdd74a3f75c4c378d69e954944a61bb0930532a0" dependencies = [ "rand_core", "subtle", diff --git a/Cargo.toml b/Cargo.toml index 2cedce0..f75736b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,4 +35,5 @@ wnaf-memuse = ["alloc", "memuse"] maintenance = { status = "actively-developed" } [patch.crates-io] -ff = { git = "https://github.com/tarcieri/ff", branch = "rand_core/v0.10" } +# targets zkcrypto's `release-0.14.0` branch +ff = { git = "https://github.com/zkcrypto/ff", rev = "bdd74a3f75c4c378d69e954944a61bb0930532a0" } From 326b36b0c43dcb1507b89017323f43a57c3bffd8 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 May 2026 14:55:39 -0600 Subject: [PATCH 11/22] Rename `Group::try_from_rng` to `Group::try_random` Matches the naming adopted in zkcrypto/rfcs#1. --- CHANGELOG.md | 2 +- src/lib.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44138f9..197044f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ and this library adheres to Rust's notion of - `group::Group::random(rng: impl RngCore) -> Self` has been changed to `Group::random(rng: &mut R) -> Self`, to enable passing a trait object as the RNG. -- `group::Group::try_from_rng` is a new trait method that must be implemented by +- `group::Group::try_random` is a new trait method that must be implemented by downstreams. `Group::random` now has a default implementation that calls it. - The curve-related traits have been refactored around the new `CurveAffine` trait: diff --git a/src/lib.rs b/src/lib.rs index 1055d76..114bc95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,12 +78,12 @@ pub trait Group: /// /// This function is non-deterministic, and samples from the user-provided RNG. fn random(rng: &mut R) -> Self { - Self::try_from_rng(rng) + Self::try_random(rng) .map_err(|e: Infallible| e) .expect("Infallible failed") // NOTE: once MSRV gets to 1.82 remove the map_err/expect and use - // let Ok(out) = Self::try_from_rng(rng); + // let Ok(out) = Self::try_random(rng); // out // See: https://blog.rust-lang.org/2024/10/17/Rust-1.82.0.html#omitting-empty-types-in-pattern-matching } @@ -92,7 +92,7 @@ pub trait Group: /// this group. /// /// This function is non-deterministic, and samples from the user-provided RNG. - fn try_from_rng(rng: &mut R) -> Result; + fn try_random(rng: &mut R) -> Result; /// Returns the additive identity, also known as the "neutral element". fn identity() -> Self; From d24dd0dd455bd99cc6555b04dd9ccad78adc4823 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 May 2026 17:01:32 -0600 Subject: [PATCH 12/22] Update to `ff 0.14.0-pre.1` --- Cargo.lock | 5 +++-- Cargo.toml | 6 +----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce53cf9..bcb364f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,8 +4,9 @@ version = 4 [[package]] name = "ff" -version = "0.14.0-pre.0" -source = "git+https://github.com/zkcrypto/ff?rev=bdd74a3f75c4c378d69e954944a61bb0930532a0#bdd74a3f75c4c378d69e954944a61bb0930532a0" +version = "0.14.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d1fa20678d31fcd57b1e146f5ca2c24282428601f45a1002a0d2a54136ef681" dependencies = [ "rand_core", "subtle", diff --git a/Cargo.toml b/Cargo.toml index f75736b..b3f660b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ homepage = "https://github.com/zkcrypto/group" repository = "https://github.com/zkcrypto/group" [dependencies] -ff = { version = "=0.14.0-pre.0", default-features = false } +ff = { version = "=0.14.0-pre.1", default-features = false } rand = { version = "0.10", optional = true, default-features = false } rand_core = { version = "0.10", default-features = false } rand_xorshift = { version = "0.5", optional = true } @@ -33,7 +33,3 @@ wnaf-memuse = ["alloc", "memuse"] [badges] maintenance = { status = "actively-developed" } - -[patch.crates-io] -# targets zkcrypto's `release-0.14.0` branch -ff = { git = "https://github.com/zkcrypto/ff", rev = "bdd74a3f75c4c378d69e954944a61bb0930532a0" } From b8220c804f2dc5402d6ad03e50de36041686249d Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 May 2026 17:06:35 -0600 Subject: [PATCH 13/22] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 197044f..b798a0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,12 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Added - `group::CurveAffine` +- `group::Group::mul_by_generator`, with a default implementation. Implementors + can override it to take advantage of precomputed tables. ### Changed -- MSRV is now 1.63.0. -- Migrated to `ff 0.14`, `rand_core 0.9`. +- MSRV is now 1.85.0. +- Migrated to `ff 0.14`, `rand_core 0.10`. - `group::Group::random(rng: impl RngCore) -> Self` has been changed to `Group::random(rng: &mut R) -> Self`, to enable passing a trait object as the RNG. From b71b98a1c115097a6f8988c13d944638589211a9 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 May 2026 17:07:54 -0600 Subject: [PATCH 14/22] Preview 0.14.0-pre.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bcb364f..83e233a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ dependencies = [ [[package]] name = "group" -version = "0.14.0-pre.0" +version = "0.14.0-pre.1" dependencies = [ "ff", "memuse", diff --git a/Cargo.toml b/Cargo.toml index b3f660b..730d5d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "group" -version = "0.14.0-pre.0" +version = "0.14.0-pre.1" authors = [ "Sean Bowe ", "Jack Grigg ", From 0562c202198ba167dbfed7aa578863b57ee1b035 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 09:54:31 -0600 Subject: [PATCH 15/22] Update CHANGELOG.md --- CHANGELOG.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b798a0d..1e3dbd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,18 +7,21 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Added -- `group::CurveAffine` +- `group::CurveAffine`, an affine-representation trait that the curve-specific + affine traits are now built on top of. - `group::Group::mul_by_generator`, with a default implementation. Implementors can override it to take advantage of precomputed tables. +- `group::Group::try_random(rng: &mut R) -> Result`, + a new trait method that must be implemented by downstreams. It samples a + non-identity group element using a fallible RNG and propagates the RNG's error. ### Changed - MSRV is now 1.85.0. - Migrated to `ff 0.14`, `rand_core 0.10`. - `group::Group::random(rng: impl RngCore) -> Self` has been changed to - `Group::random(rng: &mut R) -> Self`, to enable passing a - trait object as the RNG. -- `group::Group::try_random` is a new trait method that must be implemented by - downstreams. `Group::random` now has a default implementation that calls it. + `Group::random(rng: &mut R) -> Self`, to enable passing a + trait object as the RNG. It now has a default implementation in terms of + `Group::try_random`. - The curve-related traits have been refactored around the new `CurveAffine` trait: - `group::Curve::AffineRepr` has been renamed to `Curve::Affine`. From 8b8e53b3547d4f7714ecc4b7fc322a17e622ab90 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 09:55:10 -0600 Subject: [PATCH 16/22] Update MSRV in README.md to 1.85 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index efff81c..fd57744 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ wider discussion. ## Minimum Supported Rust Version -Requires Rust **1.63** or higher. +Requires Rust **1.85** or higher. Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump. From d0bed6d55c90bea5edf8c5d4da32a31c11d011cb Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 09:56:19 -0600 Subject: [PATCH 17/22] Update to ff 0.14.0 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83e233a..1564ee2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ff" -version = "0.14.0-pre.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1fa20678d31fcd57b1e146f5ca2c24282428601f45a1002a0d2a54136ef681" +checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f" dependencies = [ "rand_core", "subtle", diff --git a/Cargo.toml b/Cargo.toml index 730d5d2..857b0c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ homepage = "https://github.com/zkcrypto/group" repository = "https://github.com/zkcrypto/group" [dependencies] -ff = { version = "=0.14.0-pre.1", default-features = false } +ff = { version = "0.14", default-features = false } rand = { version = "0.10", optional = true, default-features = false } rand_core = { version = "0.10", default-features = false } rand_xorshift = { version = "0.5", optional = true } From 1d0579607e23ec2875cdb4dd03295d35092f5342 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 09:57:19 -0600 Subject: [PATCH 18/22] Use consistent CHANGELOG language for ff bump --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e3dbd9..04cac04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this library adheres to Rust's notion of ### Changed - MSRV is now 1.85.0. -- Migrated to `ff 0.14`, `rand_core 0.10`. +- Bumped dependencies to `ff 0.14`, `rand_core 0.10`. - `group::Group::random(rng: impl RngCore) -> Self` has been changed to `Group::random(rng: &mut R) -> Self`, to enable passing a trait object as the RNG. It now has a default implementation in terms of From 5e5b9b9791bae1a9880cd46b02cc113184f13759 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 09:59:53 -0600 Subject: [PATCH 19/22] Fix lints and minor nits --- src/lib.rs | 11 ++--------- src/tests/mod.rs | 2 +- src/wnaf.rs | 6 +++--- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 114bc95..5d0c520 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,6 @@ extern crate alloc; // Re-export ff to make version-matching easier. pub use ff; -use core::convert::Infallible; use core::fmt; use core::iter::Sum; use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; @@ -78,14 +77,8 @@ pub trait Group: /// /// This function is non-deterministic, and samples from the user-provided RNG. fn random(rng: &mut R) -> Self { - Self::try_random(rng) - .map_err(|e: Infallible| e) - .expect("Infallible failed") - - // NOTE: once MSRV gets to 1.82 remove the map_err/expect and use - // let Ok(out) = Self::try_random(rng); - // out - // See: https://blog.rust-lang.org/2024/10/17/Rust-1.82.0.html#omitting-empty-types-in-pattern-matching + let Ok(out) = Self::try_random(rng); + out } /// Returns an element chosen uniformly at random from the non-identity elements of diff --git a/src/tests/mod.rs b/src/tests/mod.rs index a598e50..d5f6b1f 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -305,7 +305,7 @@ fn random_addition_tests() { assert_eq!(aplusa, aplusamixed); } - let mut tmp = vec![G::identity(); 6]; + let mut tmp = [G::identity(); 6]; // (a + b) + c tmp[0] = a; diff --git a/src/wnaf.rs b/src/wnaf.rs index fdcf432..5adaf66 100644 --- a/src/wnaf.rs +++ b/src/wnaf.rs @@ -340,7 +340,7 @@ impl<'a, G: Group> Wnaf> { } #[cfg(feature = "wnaf-memuse")] -impl<'a, G: Group> memuse::DynamicUsage for Wnaf> { +impl memuse::DynamicUsage for Wnaf> { fn dynamic_usage(&self) -> usize { // The heap memory for the window table is counted in the parent `Wnaf`. self.scalar.dynamic_usage() @@ -365,7 +365,7 @@ impl<'a, G: Group> Wnaf, &'a [i64]> { } #[cfg(feature = "wnaf-memuse")] -impl<'a, G: Group + memuse::DynamicUsage> memuse::DynamicUsage for Wnaf, &'a [i64]> { +impl memuse::DynamicUsage for Wnaf, &[i64]> { fn dynamic_usage(&self) -> usize { // The heap memory for the scalar representation is counted in the parent `Wnaf`. self.base.dynamic_usage() @@ -432,7 +432,7 @@ impl WnafScalar { WnafScalar { wnaf, - field: PhantomData::default(), + field: PhantomData, } } } From ab8653349d5c440ce829ff929d79b096a7f5d76b Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 11:36:04 -0600 Subject: [PATCH 20/22] Simplify Curve::Affine bounds --- src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5d0c520..d6b1c84 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -110,9 +110,7 @@ pub trait Group: /// Efficient representation of an elliptic curve point. pub trait Curve: Group + GroupOps + GroupOpsOwned { /// The affine representation for this elliptic curve. - type Affine: CurveAffine - + Mul - + for<'r> Mul<&'r Self::Scalar, Output = Self>; + type Affine: CurveAffine; /// Converts a batch of projective elements into affine elements. This function will /// panic if `p.len() != q.len()`. From 7fc1ccc1c2a75e3ddbdb29638dd28b17549a05af Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 11:38:11 -0600 Subject: [PATCH 21/22] Align group random docs with ff --- src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d6b1c84..46cd0a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,18 +73,22 @@ pub trait Group: type Scalar: PrimeField; /// Returns an element chosen uniformly at random from the non-identity elements of - /// this group. + /// this group using a user-provided infallible RNG. /// - /// This function is non-deterministic, and samples from the user-provided RNG. + /// This is a convenience wrapper around [`Group::try_random`] for RNGs that cannot + /// fail. Use [`Group::try_random`] if your RNG may fail (for example, an OS-backed + /// entropy source). fn random(rng: &mut R) -> Self { let Ok(out) = Self::try_random(rng); out } /// Returns an element chosen uniformly at random from the non-identity elements of - /// this group. + /// this group using a user-provided fallible RNG. /// - /// This function is non-deterministic, and samples from the user-provided RNG. + /// Returns `Err` propagating the RNG's error if the underlying RNG fails to produce + /// the randomness required to sample an element. Implementors of `Group` must + /// provide this method; [`Group::random`] is derived from it for infallible RNGs. fn try_random(rng: &mut R) -> Result; /// Returns the additive identity, also known as the "neutral element". From f9a84a7587f47fab4ad65a25b58c8a01d1b26d39 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 30 May 2026 10:04:20 -0600 Subject: [PATCH 22/22] Release 0.14.0 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04cac04..7cf6177 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.14.0] - 2026-06-01 ### Added - `group::CurveAffine`, an affine-representation trait that the curve-specific affine traits are now built on top of. diff --git a/Cargo.lock b/Cargo.lock index 1564ee2..a00b43c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ dependencies = [ [[package]] name = "group" -version = "0.14.0-pre.1" +version = "0.14.0" dependencies = [ "ff", "memuse", diff --git a/Cargo.toml b/Cargo.toml index 857b0c1..236d244 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "group" -version = "0.14.0-pre.1" +version = "0.14.0" authors = [ "Sean Bowe ", "Jack Grigg ",