From de9bea9c5daa6a70fc0fc436513948f460ea5d01 Mon Sep 17 00:00:00 2001 From: han0110 Date: Sat, 27 May 2023 11:58:14 +0000 Subject: [PATCH 1/6] feat: implement svdw hash-to-curve for bn254 and grumpkin --- Cargo.toml | 1 + src/bn256/curve.rs | 8 ++ src/derive/curve.rs | 5 +- src/grumpkin/curve.rs | 7 ++ src/hash_to_curve.rs | 200 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 +- src/secp256k1/curve.rs | 1 + src/secp256r1/curve.rs | 1 + src/tests/curve.rs | 15 +++- 9 files changed, 238 insertions(+), 5 deletions(-) create mode 100644 src/hash_to_curve.rs diff --git a/Cargo.toml b/Cargo.toml index 226483e8..0524dbe1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ num-traits = "0.2" paste = "1.0.11" serde = { version = "1.0", default-features = false, optional = true } serde_arrays = { version = "0.1.0", optional = true } +blake2b_simd = "1" [features] default = ["reexport", "bits"] diff --git a/src/bn256/curve.rs b/src/bn256/curve.rs index 2a6b9123..c2e45a01 100644 --- a/src/bn256/curve.rs +++ b/src/bn256/curve.rs @@ -10,6 +10,7 @@ use crate::ff::WithSmallOrderMulGroup; use crate::ff::{Field, PrimeField}; use crate::group::Curve; use crate::group::{cofactor::CofactorGroup, prime::PrimeCurveAffine, Group, GroupEncoding}; +use crate::hash_to_curve::svdw_map_to_curve; use crate::{ batch_add, impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative, @@ -38,6 +39,7 @@ new_curve_impl!( G1_A, G1_B, "bn256_g1", + |curve_id, domain_prefix| svdw_map_to_curve(curve_id, domain_prefix, Fq::ONE), ); new_curve_impl!( @@ -51,6 +53,7 @@ new_curve_impl!( G2_A, G2_B, "bn256_g2", + |_, _| unimplemented!(), ); impl CurveAffineExt for G1Affine { @@ -223,6 +226,11 @@ mod tests { use ff::WithSmallOrderMulGroup; use rand_core::OsRng; + #[test] + fn test_hash_to_curve() { + crate::tests::curve::hash_to_curve_test::(); + } + #[test] fn test_curve() { crate::tests::curve::curve_tests::(); diff --git a/src/derive/curve.rs b/src/derive/curve.rs index f733340f..f4173683 100644 --- a/src/derive/curve.rs +++ b/src/derive/curve.rs @@ -203,6 +203,7 @@ macro_rules! new_curve_impl { $constant_a:expr, $constant_b:expr, $curve_id:literal, + $hash_to_curve:expr, ) => { macro_rules! impl_compressed { @@ -615,8 +616,8 @@ macro_rules! new_curve_impl { } - fn hash_to_curve<'a>(_: &'a str) -> Box Self + 'a> { - unimplemented!(); + fn hash_to_curve<'a>(domain_prefix: &'a str) -> Box Self + 'a> { + $hash_to_curve($curve_id, domain_prefix) } fn is_on_curve(&self) -> Choice { diff --git a/src/grumpkin/curve.rs b/src/grumpkin/curve.rs index 4f70259f..8936a07a 100644 --- a/src/grumpkin/curve.rs +++ b/src/grumpkin/curve.rs @@ -4,6 +4,7 @@ use crate::group::Curve; use crate::group::{prime::PrimeCurveAffine, Group, GroupEncoding}; use crate::grumpkin::Fq; use crate::grumpkin::Fr; +use crate::hash_to_curve::svdw_map_to_curve; use crate::{ batch_add, impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative, @@ -31,6 +32,7 @@ new_curve_impl!( G1_A, G1_B, "grumpkin_g1", + |curve_id, domain_prefix| svdw_map_to_curve(curve_id, domain_prefix, Fq::ONE), ); impl CurveAffineExt for G1Affine { @@ -80,6 +82,11 @@ mod tests { use crate::CurveExt; use ff::WithSmallOrderMulGroup; + #[test] + fn test_hash_to_curve() { + crate::tests::curve::hash_to_curve_test::(); + } + #[test] fn test_curve() { crate::tests::curve::curve_tests::(); diff --git a/src/hash_to_curve.rs b/src/hash_to_curve.rs new file mode 100644 index 00000000..dc1e6a45 --- /dev/null +++ b/src/hash_to_curve.rs @@ -0,0 +1,200 @@ +#![allow(clippy::op_ref)] + +use ff::{Field, FromUniformBytes, PrimeField}; +use pasta_curves::arithmetic::CurveExt; +use static_assertions::const_assert; +use subtle::{ConditionallySelectable, ConstantTimeEq}; + +/// Hashes over a message and writes the output to all of `buf`. +/// Modified from https://github.com/zcash/pasta_curves/blob/7e3fc6a4919f6462a32b79dd226cb2587b7961eb/src/hashtocurve.rs#L11. +fn hash_to_field>( + method: &str, + curve_id: &str, + domain_prefix: &str, + message: &[u8], + buf: &mut [F; 2], +) { + assert!(domain_prefix.len() < 256); + assert!((18 + method.len() + curve_id.len() + domain_prefix.len()) < 256); + + // Assume that the field size is 32 bytes and k is 256, where k is defined in + // . + const CHUNKLEN: usize = 64; + const_assert!(CHUNKLEN * 2 < 256); + + // Input block size of BLAKE2b. + const R_IN_BYTES: usize = 128; + + let personal = [0u8; 16]; + let empty_hasher = blake2b_simd::Params::new() + .hash_length(CHUNKLEN) + .personal(&personal) + .to_state(); + + let b_0 = empty_hasher + .clone() + .update(&[0; R_IN_BYTES]) + .update(message) + .update(&[0, (CHUNKLEN * 2) as u8, 0]) + .update(domain_prefix.as_bytes()) + .update(b"-") + .update(curve_id.as_bytes()) + .update(b"_XMD:BLAKE2b_") + .update(method.as_bytes()) + .update(b"_RO_") + .update(&[(18 + method.len() + curve_id.len() + domain_prefix.len()) as u8]) + .finalize(); + + let b_1 = empty_hasher + .clone() + .update(b_0.as_array()) + .update(&[1]) + .update(domain_prefix.as_bytes()) + .update(b"-") + .update(curve_id.as_bytes()) + .update(b"_XMD:BLAKE2b_") + .update(method.as_bytes()) + .update(b"_RO_") + .update(&[(18 + method.len() + curve_id.len() + domain_prefix.len()) as u8]) + .finalize(); + + let b_2 = { + let mut empty_hasher = empty_hasher; + for (l, r) in b_0.as_array().iter().zip(b_1.as_array().iter()) { + empty_hasher.update(&[*l ^ *r]); + } + empty_hasher + .update(&[2]) + .update(domain_prefix.as_bytes()) + .update(b"-") + .update(curve_id.as_bytes()) + .update(b"_XMD:BLAKE2b_") + .update(method.as_bytes()) + .update(b"_RO_") + .update(&[(18 + method.len() + curve_id.len() + domain_prefix.len()) as u8]) + .finalize() + }; + + for (big, buf) in [b_1, b_2].iter().zip(buf.iter_mut()) { + let mut little = [0u8; CHUNKLEN]; + little.copy_from_slice(big.as_array()); + little.reverse(); + *buf = F::from_uniform_bytes(&little); + } +} + +/// Implementation of https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-16.html#name-shallue-van-de-woestijne-met +#[allow(clippy::type_complexity)] +pub(crate) fn svdw_map_to_curve<'a, C>( + curve_id: &'static str, + domain_prefix: &'a str, + z: C::Base, +) -> Box C + 'a> +where + C: CurveExt, + C::Base: FromUniformBytes<64>, +{ + let one = C::Base::ONE; + let three = one + one + one; + let four = three + one; + let a = C::a(); + let b = C::b(); + let tmp = three * z.square() + four * a; + + // Precomputed constants: + // 1. c1 = g(Z) + let c1 = (z.square() + a) * z + b; + // 2. c2 = -Z / 2 + let c2 = -z * C::Base::TWO_INV; + // 3. c3 = sqrt(-g(Z) * (3 * Z^2 + 4 * A)) # sgn0(c3) MUST equal 0 + let c3 = { + let c3 = (-c1 * tmp).sqrt().unwrap(); + C::Base::conditional_select(&c3, &-c3, c3.is_odd()) + }; + // 4. c4 = -4 * g(Z) / (3 * Z^2 + 4 * A) + let c4 = -four * c1 * tmp.invert().unwrap(); + + Box::new(move |message| { + let mut us = [C::Base::ZERO; 2]; + hash_to_field("SVDW", curve_id, domain_prefix, message, &mut us); + + let [q0, q1] = us.map(|u| { + // 1. tv1 = u^2 + let tv1 = u.square(); + // 2. tv1 = tv1 * c1 + let tv1 = tv1 * c1; + // 3. tv2 = 1 + tv1 + let tv2 = one + tv1; + // 4. tv1 = 1 - tv1 + let tv1 = one - tv1; + // 5. tv3 = tv1 * tv2 + let tv3 = tv1 * tv2; + // 6. tv3 = inv0(tv3) + let tv3 = tv3.invert().unwrap_or(C::Base::ZERO); + // 7. tv4 = u * tv1 + let tv4 = u * tv1; + // 8. tv4 = tv4 * tv3 + let tv4 = tv4 * tv3; + // 9. tv4 = tv4 * c3 + let tv4 = tv4 * c3; + // 10. x1 = c2 - tv4 + let x1 = c2 - tv4; + // 11. gx1 = x1^2 + let gx1 = x1.square(); + // 12. gx1 = gx1 + A + let gx1 = gx1 + a; + // 13. gx1 = gx1 * x1 + let gx1 = gx1 * x1; + // 14. gx1 = gx1 + B + let gx1 = gx1 + b; + // 15. e1 = is_square(gx1) + let e1 = gx1.sqrt().is_some(); + // 16. x2 = c2 + tv4 + let x2 = c2 + tv4; + // 17. gx2 = x2^2 + let gx2 = x2.square(); + // 18. gx2 = gx2 + A + let gx2 = gx2 + a; + // 19. gx2 = gx2 * x2 + let gx2 = gx2 * x2; + // 20. gx2 = gx2 + B + let gx2 = gx2 + b; + // 21. e2 = is_square(gx2) AND NOT e1 # Avoid short-circuit logic ops + let e2 = gx2.sqrt().is_some() & (!e1); + // 22. x3 = tv2^2 + let x3 = tv2.square(); + // 23. x3 = x3 * tv3 + let x3 = x3 * tv3; + // 24. x3 = x3^2 + let x3 = x3.square(); + // 25. x3 = x3 * c4 + let x3 = x3 * c4; + // 26. x3 = x3 + Z + let x3 = x3 + z; + // 27. x = CMOV(x3, x1, e1) # x = x1 if gx1 is square, else x = x3 + let x = C::Base::conditional_select(&x3, &x1, e1); + // 28. x = CMOV(x, x2, e2) # x = x2 if gx2 is square and gx1 is not + let x = C::Base::conditional_select(&x, &x2, e2); + // 29. gx = x^2 + let gx = x.square(); + // 30. gx = gx + A + let gx = gx + a; + // 31. gx = gx * x + let gx = gx * x; + // 32. gx = gx + B + let gx = gx + b; + // 33. y = sqrt(gx) + let y = gx.sqrt().unwrap(); + // 34. e3 = sgn0(u) == sgn0(y) + let e3 = u.is_odd().ct_eq(&y.is_odd()); + // 35. y = CMOV(-y, y, e3) # Select correct sign of y + let y = C::Base::conditional_select(&-y, &y, e3); + // 36. return (x, y) + C::new_jacobian(x, y, one).unwrap() + }); + + let r = q0 + &q1; + debug_assert!(bool::from(r.is_on_curve())); + r + }) +} diff --git a/src/lib.rs b/src/lib.rs index 53a3f251..0b1f537c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,15 @@ #![cfg_attr(feature = "asm", feature(asm_const))] mod arithmetic; +pub mod hash_to_curve; +pub mod pairing; +pub mod serde; pub mod bn256; pub mod grumpkin; -pub mod pairing; pub mod pasta; pub mod secp256k1; pub mod secp256r1; -pub mod serde; #[macro_use] mod derive; diff --git a/src/secp256k1/curve.rs b/src/secp256k1/curve.rs index 2021f19a..5ca03d6a 100644 --- a/src/secp256k1/curve.rs +++ b/src/secp256k1/curve.rs @@ -64,6 +64,7 @@ new_curve_impl!( SECP_A, SECP_B, "secp256k1", + |_, _| unimplemented!(), ); impl CurveAffineExt for Secp256k1Affine { diff --git a/src/secp256r1/curve.rs b/src/secp256r1/curve.rs index c4c4422b..77a87a4f 100644 --- a/src/secp256r1/curve.rs +++ b/src/secp256r1/curve.rs @@ -75,6 +75,7 @@ new_curve_impl!( SECP_A, SECP_B, "secp256r1", + |_, _| unimplemented!(), ); impl CurveAffineExt for Secp256r1Affine { diff --git a/src/tests/curve.rs b/src/tests/curve.rs index 3a22c588..2573dc19 100644 --- a/src/tests/curve.rs +++ b/src/tests/curve.rs @@ -4,7 +4,8 @@ use crate::ff::Field; use crate::group::prime::PrimeCurveAffine; use crate::{group::GroupEncoding, serde::SerdeObject}; use crate::{CurveAffine, CurveExt}; -use rand_core::OsRng; +use rand_core::{OsRng, RngCore}; +use std::iter; #[cfg(feature = "derive_serde")] use serde::{Deserialize, Serialize}; @@ -314,3 +315,15 @@ fn multiplication() { assert_eq!(t0, t1); } } + +pub fn hash_to_curve_test() { + let hasher = G::hash_to_curve("test"); + let mut rng = OsRng; + for _ in 0..1000 { + let message = iter::repeat_with(|| rng.next_u32().to_be_bytes()) + .take(32) + .flatten() + .collect::>(); + assert!(bool::from(hasher(&message).is_on_curve())); + } +} From bc520081bd4cc86397b1d3af8177f42b6456b07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Mon, 12 Jun 2023 11:03:37 -0400 Subject: [PATCH 2/6] refactor: split svdw_map_to_curve into map_to_curve - Refactor svdw_map_to_curve function for better modularity - Update map_to_curve function to accept precomputed constants and curve values --- src/hash_to_curve.rs | 166 ++++++++++++++++++++++++------------------- 1 file changed, 92 insertions(+), 74 deletions(-) diff --git a/src/hash_to_curve.rs b/src/hash_to_curve.rs index dc1e6a45..8b9286c6 100644 --- a/src/hash_to_curve.rs +++ b/src/hash_to_curve.rs @@ -83,6 +83,97 @@ fn hash_to_field>( } } +#[allow(clippy::too_many_arguments)] +pub(crate) fn map_to_curve( + u: C::Base, + c1: &C::Base, + c2: C::Base, + c3: &C::Base, + c4: &C::Base, + a: &C::Base, + b: &C::Base, + z: &C::Base, +) -> C +where + C: CurveExt, + C::Base: FromUniformBytes<64>, +{ + let one = C::Base::ONE; + + // 1. tv1 = u^2 + let tv1 = u.square(); + // 2. tv1 = tv1 * c1 + let tv1 = tv1 * c1; + // 3. tv2 = 1 + tv1 + let tv2 = one + tv1; + // 4. tv1 = 1 - tv1 + let tv1 = one - tv1; + // 5. tv3 = tv1 * tv2 + let tv3 = tv1 * tv2; + // 6. tv3 = inv0(tv3) + let tv3 = tv3.invert().unwrap_or(C::Base::ZERO); + // 7. tv4 = u * tv1 + let tv4 = u * tv1; + // 8. tv4 = tv4 * tv3 + let tv4 = tv4 * tv3; + // 9. tv4 = tv4 * c3 + let tv4 = tv4 * c3; + // 10. x1 = c2 - tv4 + let x1 = c2 - tv4; + // 11. gx1 = x1^2 + let gx1 = x1.square(); + // 12. gx1 = gx1 + A + let gx1 = gx1 + a; + // 13. gx1 = gx1 * x1 + let gx1 = gx1 * x1; + // 14. gx1 = gx1 + B + let gx1 = gx1 + b; + // 15. e1 = is_square(gx1) + let e1 = gx1.sqrt().is_some(); + // 16. x2 = c2 + tv4 + let x2 = c2 + tv4; + // 17. gx2 = x2^2 + let gx2 = x2.square(); + // 18. gx2 = gx2 + A + let gx2 = gx2 + a; + // 19. gx2 = gx2 * x2 + let gx2 = gx2 * x2; + // 20. gx2 = gx2 + B + let gx2 = gx2 + b; + // 21. e2 = is_square(gx2) AND NOT e1 # Avoid short-circuit logic ops + let e2 = gx2.sqrt().is_some() & (!e1); + // 22. x3 = tv2^2 + let x3 = tv2.square(); + // 23. x3 = x3 * tv3 + let x3 = x3 * tv3; + // 24. x3 = x3^2 + let x3 = x3.square(); + // 25. x3 = x3 * c4 + let x3 = x3 * c4; + // 26. x3 = x3 + Z + let x3 = x3 + z; + // 27. x = CMOV(x3, x1, e1) # x = x1 if gx1 is square, else x = x3 + let x = C::Base::conditional_select(&x3, &x1, e1); + // 28. x = CMOV(x, x2, e2) # x = x2 if gx2 is square and gx1 is not + let x = C::Base::conditional_select(&x, &x2, e2); + // 29. gx = x^2 + let gx = x.square(); + // 30. gx = gx + A + let gx = gx + a; + // 31. gx = gx * x + let gx = gx * x; + // 32. gx = gx + B + let gx = gx + b; + // 33. y = sqrt(gx) + let y = gx.sqrt().unwrap(); + // 34. e3 = sgn0(u) == sgn0(y) + let e3 = u.is_odd().ct_eq(&y.is_odd()); + // 35. y = CMOV(-y, y, e3) # Select correct sign of y + let y = C::Base::conditional_select(&-y, &y, e3); + // 36. return (x, y) + C::new_jacobian(x, y, one).unwrap() +} + /// Implementation of https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-16.html#name-shallue-van-de-woestijne-met #[allow(clippy::type_complexity)] pub(crate) fn svdw_map_to_curve<'a, C>( @@ -118,80 +209,7 @@ where let mut us = [C::Base::ZERO; 2]; hash_to_field("SVDW", curve_id, domain_prefix, message, &mut us); - let [q0, q1] = us.map(|u| { - // 1. tv1 = u^2 - let tv1 = u.square(); - // 2. tv1 = tv1 * c1 - let tv1 = tv1 * c1; - // 3. tv2 = 1 + tv1 - let tv2 = one + tv1; - // 4. tv1 = 1 - tv1 - let tv1 = one - tv1; - // 5. tv3 = tv1 * tv2 - let tv3 = tv1 * tv2; - // 6. tv3 = inv0(tv3) - let tv3 = tv3.invert().unwrap_or(C::Base::ZERO); - // 7. tv4 = u * tv1 - let tv4 = u * tv1; - // 8. tv4 = tv4 * tv3 - let tv4 = tv4 * tv3; - // 9. tv4 = tv4 * c3 - let tv4 = tv4 * c3; - // 10. x1 = c2 - tv4 - let x1 = c2 - tv4; - // 11. gx1 = x1^2 - let gx1 = x1.square(); - // 12. gx1 = gx1 + A - let gx1 = gx1 + a; - // 13. gx1 = gx1 * x1 - let gx1 = gx1 * x1; - // 14. gx1 = gx1 + B - let gx1 = gx1 + b; - // 15. e1 = is_square(gx1) - let e1 = gx1.sqrt().is_some(); - // 16. x2 = c2 + tv4 - let x2 = c2 + tv4; - // 17. gx2 = x2^2 - let gx2 = x2.square(); - // 18. gx2 = gx2 + A - let gx2 = gx2 + a; - // 19. gx2 = gx2 * x2 - let gx2 = gx2 * x2; - // 20. gx2 = gx2 + B - let gx2 = gx2 + b; - // 21. e2 = is_square(gx2) AND NOT e1 # Avoid short-circuit logic ops - let e2 = gx2.sqrt().is_some() & (!e1); - // 22. x3 = tv2^2 - let x3 = tv2.square(); - // 23. x3 = x3 * tv3 - let x3 = x3 * tv3; - // 24. x3 = x3^2 - let x3 = x3.square(); - // 25. x3 = x3 * c4 - let x3 = x3 * c4; - // 26. x3 = x3 + Z - let x3 = x3 + z; - // 27. x = CMOV(x3, x1, e1) # x = x1 if gx1 is square, else x = x3 - let x = C::Base::conditional_select(&x3, &x1, e1); - // 28. x = CMOV(x, x2, e2) # x = x2 if gx2 is square and gx1 is not - let x = C::Base::conditional_select(&x, &x2, e2); - // 29. gx = x^2 - let gx = x.square(); - // 30. gx = gx + A - let gx = gx + a; - // 31. gx = gx * x - let gx = gx * x; - // 32. gx = gx + B - let gx = gx + b; - // 33. y = sqrt(gx) - let y = gx.sqrt().unwrap(); - // 34. e3 = sgn0(u) == sgn0(y) - let e3 = u.is_odd().ct_eq(&y.is_odd()); - // 35. y = CMOV(-y, y, e3) # Select correct sign of y - let y = C::Base::conditional_select(&-y, &y, e3); - // 36. return (x, y) - C::new_jacobian(x, y, one).unwrap() - }); + let [q0, q1]: [C; 2] = us.map(|u| map_to_curve(u, &c1, c2, &c3, &c4, &a, &b, &z)); let r = q0 + &q1; debug_assert!(bool::from(r.is_on_curve())); From 62540c6c4e38c83c737a61954847b8f294fd598d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Mon, 12 Jun 2023 11:04:32 -0400 Subject: [PATCH 3/6] Add test vectors from gnark-crypto for map_to_curve --- src/bn256/curve.rs | 126 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 3 deletions(-) diff --git a/src/bn256/curve.rs b/src/bn256/curve.rs index c2e45a01..516f390a 100644 --- a/src/bn256/curve.rs +++ b/src/bn256/curve.rs @@ -219,11 +219,16 @@ impl CofactorGroup for G2 { mod tests { use crate::arithmetic::CurveEndo; - use crate::bn256::{Fr, G1, G2}; + use crate::bn256::{Fq, Fr, G1Affine, G1, G2}; + use crate::hash_to_curve::map_to_curve; + use crate::serde::SerdeObject; use crate::CurveExt; use ff::Field; - use ff::PrimeField; - use ff::WithSmallOrderMulGroup; + use ff::{PrimeField, WithSmallOrderMulGroup}; + use group::Curve; + use num_bigint::BigUint; + use num_traits::Num; + use pasta_curves::arithmetic::CurveAffine; use rand_core::OsRng; #[test] @@ -231,6 +236,121 @@ mod tests { crate::tests::curve::hash_to_curve_test::(); } + #[test] + fn test_map_to_curve_bn256() { + // from https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/bn254/hash_vectors_test.go + let encode_tests = vec![ + ( + //u + "0xcb81538a98a2e3580076eed495256611813f6dae9e16d3d4f8de7af0e9833e1", + // Q + ( + "0x1bb8810e2ceaf04786d4efd216fc2820ddd9363712efc736ada11049d8af5925", + "0x1efbf8d54c60d865cce08437668ea30f5bf90d287dbd9b5af31da852915e8f11", + ), + ), + ( + //u + "0xba35e127276e9000b33011860904ddee28f1d48ddd3577e2a797ef4a5e62319", + // Q + ( + "0xda4a96147df1f35b0f820bd35c6fac3b80e8e320de7c536b1e054667b22c332", + "0x189bd3fbffe4c8740d6543754d95c790e44cd2d162858e3b733d2b8387983bb7", + ), + ), + ( + //u + "0x11852286660cd970e9d7f46f99c7cca2b75554245e91b9b19d537aa6147c28fc", + // Q + ( + "0x2ff727cfaaadb3acab713fa22d91f5fddab3ed77948f3ef6233d7ea9b03f4da1", + "0x304080768fd2f87a852155b727f97db84b191e41970506f0326ed4046d1141aa", + ), + ), + ( + //u + "0x174d1c85d8a690a876cc1deba0166d30569fafdb49cb3ed28405bd1c5357a1cc", + // Q + ( + "0x11a2eaa8e3e89de056d1b3a288a7f733c8a1282efa41d28e71af065ab245df9b", + "0x60f37c447ac29fd97b9bb83be98ddccf15e34831a9cdf5493b7fede0777ae06", + ), + ), + ( + //u + "0x73b81432b4cf3a8a9076201500d1b94159539f052a6e0928db7f2df74bff672", + // Q + ( + "0x27409dccc6ee4ce90e24744fda8d72c0bc64e79766f778da0c1c0ef1c186ea84", + "0x1ac201a542feca15e77f30370da183514dc99d8a0b2c136d64ede35cd0b51dc0", + ), + ), + ]; + + // inspired by TestMapToCurve1 in + // https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/bn254/hash_to_g1_test.go + for (u, pt_q) in encode_tests { + let big_u = BigUint::from_str_radix(&u.strip_prefix("0x").unwrap(), 16) + .unwrap() + .to_string(); + let u = Fq::from_str_vartime(&big_u).unwrap(); + + println!("{:x?}", u); + + let to_fq = |arg: [u64; 4]| { + let arg_bytes: [u8; 32] = unsafe { ::std::mem::transmute(arg) }; + Fq::from_raw_bytes_unchecked(&arg_bytes) + }; + + // from https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/bn254/hash_to_g1.go + let z = to_fq([ + 15230403791020821917, + 754611498739239741, + 7381016538464732716, + 1011752739694698287, + ]); + let c1 = to_fq([ + 1248766071674976557, + 10548065924188627562, + 16242874202584236114, + 560012691975822483, + ]); + let c2 = to_fq([ + 12997850613838968789, + 14304628359724097447, + 2950087706404981016, + 1237622763554136189, + ]); + let c3 = to_fq([ + 8972444824031832946, + 5898165201680709844, + 10690697896010808308, + 824354360198587078, + ]); + let c4 = to_fq([ + 12077013577332951089, + 1872782865047492001, + 13514471836495169457, + 415649166299893576, + ]); + + let g: G1 = map_to_curve(u, &c1, c2, &c3, &c4, &G1::a(), &G1::b(), &z); + let g_aff = g.to_affine(); + + let big_x = BigUint::from_str_radix(&pt_q.0.strip_prefix("0x").unwrap(), 16) + .unwrap() + .to_string(); + let big_y = BigUint::from_str_radix(&pt_q.1.strip_prefix("0x").unwrap(), 16) + .unwrap() + .to_string(); + let x = Fq::from_str_vartime(&big_x).unwrap(); + let y = Fq::from_str_vartime(&big_y).unwrap(); + let expected_g = G1Affine::from_xy(x, y).unwrap(); + + assert_eq!(g_aff, expected_g); + } + } + #[test] fn test_curve() { crate::tests::curve::curve_tests::(); From 972792faef1d04dfbbb3254d7a2bed0a1daf3632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Mon, 12 Jun 2023 15:56:29 -0400 Subject: [PATCH 4/6] fixup! Add test vectors from gnark-crypto for map_to_curve --- src/bn256/curve.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bn256/curve.rs b/src/bn256/curve.rs index 516f390a..9f7f7091 100644 --- a/src/bn256/curve.rs +++ b/src/bn256/curve.rs @@ -295,8 +295,6 @@ mod tests { .to_string(); let u = Fq::from_str_vartime(&big_u).unwrap(); - println!("{:x?}", u); - let to_fq = |arg: [u64; 4]| { let arg_bytes: [u8; 32] = unsafe { ::std::mem::transmute(arg) }; Fq::from_raw_bytes_unchecked(&arg_bytes) From 0db03bf35bca8ddfe9554451410980d05512224c Mon Sep 17 00:00:00 2001 From: han0110 Date: Tue, 13 Jun 2023 02:56:08 +0000 Subject: [PATCH 5/6] refactor: add `svdw_map_to_curve_test` helper in mod `tests` --- src/bn256/curve.rs | 156 +++++++++++++----------------------------- src/bn256/engine.rs | 2 +- src/grumpkin/curve.rs | 8 ++- src/hash_to_curve.rs | 48 +++++++------ src/tests/curve.rs | 18 ++++- src/tests/mod.rs | 15 ++++ 6 files changed, 111 insertions(+), 136 deletions(-) diff --git a/src/bn256/curve.rs b/src/bn256/curve.rs index 9f7f7091..3ffb4597 100644 --- a/src/bn256/curve.rs +++ b/src/bn256/curve.rs @@ -10,7 +10,7 @@ use crate::ff::WithSmallOrderMulGroup; use crate::ff::{Field, PrimeField}; use crate::group::Curve; use crate::group::{cofactor::CofactorGroup, prime::PrimeCurveAffine, Group, GroupEncoding}; -use crate::hash_to_curve::svdw_map_to_curve; +use crate::hash_to_curve::svdw_hash_to_curve; use crate::{ batch_add, impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative, @@ -39,7 +39,7 @@ new_curve_impl!( G1_A, G1_B, "bn256_g1", - |curve_id, domain_prefix| svdw_map_to_curve(curve_id, domain_prefix, Fq::ONE), + |curve_id, domain_prefix| svdw_hash_to_curve(curve_id, domain_prefix, G1::SVDW_Z), ); new_curve_impl!( @@ -215,20 +215,17 @@ impl CofactorGroup for G2 { } } +impl G1 { + const SVDW_Z: Fq = Fq::ONE; +} + #[cfg(test)] mod tests { - use crate::arithmetic::CurveEndo; - use crate::bn256::{Fq, Fr, G1Affine, G1, G2}; - use crate::hash_to_curve::map_to_curve; - use crate::serde::SerdeObject; + use crate::bn256::{Fr, G1, G2}; use crate::CurveExt; use ff::Field; use ff::{PrimeField, WithSmallOrderMulGroup}; - use group::Curve; - use num_bigint::BigUint; - use num_traits::Num; - use pasta_curves::arithmetic::CurveAffine; use rand_core::OsRng; #[test] @@ -237,116 +234,55 @@ mod tests { } #[test] - fn test_map_to_curve_bn256() { - // from https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/bn254/hash_vectors_test.go - let encode_tests = vec![ - ( - //u - "0xcb81538a98a2e3580076eed495256611813f6dae9e16d3d4f8de7af0e9833e1", - // Q + fn test_map_to_curve() { + crate::tests::curve::svdw_map_to_curve_test::( + G1::SVDW_Z, + // Precomputed constants taken from https://github.com/ConsenSys/gnark-crypto/blob/441dc0ffe639294b8d09e394f24ba7575577229c/internal/generator/config/bn254.go#L26-L32. + [ + "4", + "10944121435919637611123202872628637544348155578648911831344518947322613104291", + "8815841940592487685674414971303048083897117035520822607866", + "7296080957279758407415468581752425029565437052432607887563012631548408736189", + ], + // List of (u, (Q.x, Q.y)) taken from https://github.com/ConsenSys/gnark-crypto/blob/441dc0ffe639294b8d09e394f24ba7575577229c/ecc/bn254/hash_vectors_test.go#L4-L28 + [ ( - "0x1bb8810e2ceaf04786d4efd216fc2820ddd9363712efc736ada11049d8af5925", - "0x1efbf8d54c60d865cce08437668ea30f5bf90d287dbd9b5af31da852915e8f11", + "0xcb81538a98a2e3580076eed495256611813f6dae9e16d3d4f8de7af0e9833e1", + ( + "0x1bb8810e2ceaf04786d4efd216fc2820ddd9363712efc736ada11049d8af5925", + "0x1efbf8d54c60d865cce08437668ea30f5bf90d287dbd9b5af31da852915e8f11", + ), ), - ), - ( - //u - "0xba35e127276e9000b33011860904ddee28f1d48ddd3577e2a797ef4a5e62319", - // Q ( - "0xda4a96147df1f35b0f820bd35c6fac3b80e8e320de7c536b1e054667b22c332", - "0x189bd3fbffe4c8740d6543754d95c790e44cd2d162858e3b733d2b8387983bb7", + "0xba35e127276e9000b33011860904ddee28f1d48ddd3577e2a797ef4a5e62319", + ( + "0xda4a96147df1f35b0f820bd35c6fac3b80e8e320de7c536b1e054667b22c332", + "0x189bd3fbffe4c8740d6543754d95c790e44cd2d162858e3b733d2b8387983bb7", + ), ), - ), - ( - //u - "0x11852286660cd970e9d7f46f99c7cca2b75554245e91b9b19d537aa6147c28fc", - // Q ( - "0x2ff727cfaaadb3acab713fa22d91f5fddab3ed77948f3ef6233d7ea9b03f4da1", - "0x304080768fd2f87a852155b727f97db84b191e41970506f0326ed4046d1141aa", + "0x11852286660cd970e9d7f46f99c7cca2b75554245e91b9b19d537aa6147c28fc", + ( + "0x2ff727cfaaadb3acab713fa22d91f5fddab3ed77948f3ef6233d7ea9b03f4da1", + "0x304080768fd2f87a852155b727f97db84b191e41970506f0326ed4046d1141aa", + ), ), - ), - ( - //u - "0x174d1c85d8a690a876cc1deba0166d30569fafdb49cb3ed28405bd1c5357a1cc", - // Q ( - "0x11a2eaa8e3e89de056d1b3a288a7f733c8a1282efa41d28e71af065ab245df9b", - "0x60f37c447ac29fd97b9bb83be98ddccf15e34831a9cdf5493b7fede0777ae06", + "0x174d1c85d8a690a876cc1deba0166d30569fafdb49cb3ed28405bd1c5357a1cc", + ( + "0x11a2eaa8e3e89de056d1b3a288a7f733c8a1282efa41d28e71af065ab245df9b", + "0x60f37c447ac29fd97b9bb83be98ddccf15e34831a9cdf5493b7fede0777ae06", + ), ), - ), - ( - //u - "0x73b81432b4cf3a8a9076201500d1b94159539f052a6e0928db7f2df74bff672", - // Q ( - "0x27409dccc6ee4ce90e24744fda8d72c0bc64e79766f778da0c1c0ef1c186ea84", - "0x1ac201a542feca15e77f30370da183514dc99d8a0b2c136d64ede35cd0b51dc0", + "0x73b81432b4cf3a8a9076201500d1b94159539f052a6e0928db7f2df74bff672", + ( + "0x27409dccc6ee4ce90e24744fda8d72c0bc64e79766f778da0c1c0ef1c186ea84", + "0x1ac201a542feca15e77f30370da183514dc99d8a0b2c136d64ede35cd0b51dc0", + ), ), - ), - ]; - - // inspired by TestMapToCurve1 in - // https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/bn254/hash_to_g1_test.go - for (u, pt_q) in encode_tests { - let big_u = BigUint::from_str_radix(&u.strip_prefix("0x").unwrap(), 16) - .unwrap() - .to_string(); - let u = Fq::from_str_vartime(&big_u).unwrap(); - - let to_fq = |arg: [u64; 4]| { - let arg_bytes: [u8; 32] = unsafe { ::std::mem::transmute(arg) }; - Fq::from_raw_bytes_unchecked(&arg_bytes) - }; - - // from https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/bn254/hash_to_g1.go - let z = to_fq([ - 15230403791020821917, - 754611498739239741, - 7381016538464732716, - 1011752739694698287, - ]); - let c1 = to_fq([ - 1248766071674976557, - 10548065924188627562, - 16242874202584236114, - 560012691975822483, - ]); - let c2 = to_fq([ - 12997850613838968789, - 14304628359724097447, - 2950087706404981016, - 1237622763554136189, - ]); - let c3 = to_fq([ - 8972444824031832946, - 5898165201680709844, - 10690697896010808308, - 824354360198587078, - ]); - let c4 = to_fq([ - 12077013577332951089, - 1872782865047492001, - 13514471836495169457, - 415649166299893576, - ]); - - let g: G1 = map_to_curve(u, &c1, c2, &c3, &c4, &G1::a(), &G1::b(), &z); - let g_aff = g.to_affine(); - - let big_x = BigUint::from_str_radix(&pt_q.0.strip_prefix("0x").unwrap(), 16) - .unwrap() - .to_string(); - let big_y = BigUint::from_str_radix(&pt_q.1.strip_prefix("0x").unwrap(), 16) - .unwrap() - .to_string(); - let x = Fq::from_str_vartime(&big_x).unwrap(); - let y = Fq::from_str_vartime(&big_y).unwrap(); - let expected_g = G1Affine::from_xy(x, y).unwrap(); - - assert_eq!(g_aff, expected_g); - } + ], + ); } #[test] diff --git a/src/bn256/engine.rs b/src/bn256/engine.rs index b4da1e0a..8ed8725b 100644 --- a/src/bn256/engine.rs +++ b/src/bn256/engine.rs @@ -62,7 +62,7 @@ pub struct Gt(pub(crate) Fq12); impl std::fmt::Display for Gt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) + write!(f, "{self:?}") } } diff --git a/src/grumpkin/curve.rs b/src/grumpkin/curve.rs index 8936a07a..259b19f1 100644 --- a/src/grumpkin/curve.rs +++ b/src/grumpkin/curve.rs @@ -4,7 +4,7 @@ use crate::group::Curve; use crate::group::{prime::PrimeCurveAffine, Group, GroupEncoding}; use crate::grumpkin::Fq; use crate::grumpkin::Fr; -use crate::hash_to_curve::svdw_map_to_curve; +use crate::hash_to_curve::svdw_hash_to_curve; use crate::{ batch_add, impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative, @@ -32,7 +32,7 @@ new_curve_impl!( G1_A, G1_B, "grumpkin_g1", - |curve_id, domain_prefix| svdw_map_to_curve(curve_id, domain_prefix, Fq::ONE), + |curve_id, domain_prefix| svdw_hash_to_curve(curve_id, domain_prefix, G1::SVDW_Z), ); impl CurveAffineExt for G1Affine { @@ -76,6 +76,10 @@ impl group::cofactor::CofactorGroup for G1 { } } +impl G1 { + const SVDW_Z: Fq = Fq::ONE; +} + #[cfg(test)] mod tests { use crate::grumpkin::{Fr, G1}; diff --git a/src/hash_to_curve.rs b/src/hash_to_curve.rs index 8b9286c6..4cef7095 100644 --- a/src/hash_to_curve.rs +++ b/src/hash_to_curve.rs @@ -84,21 +84,20 @@ fn hash_to_field>( } #[allow(clippy::too_many_arguments)] -pub(crate) fn map_to_curve( +pub(crate) fn svdw_map_to_curve( u: C::Base, - c1: &C::Base, + c1: C::Base, c2: C::Base, - c3: &C::Base, - c4: &C::Base, - a: &C::Base, - b: &C::Base, - z: &C::Base, + c3: C::Base, + c4: C::Base, + z: C::Base, ) -> C where C: CurveExt, - C::Base: FromUniformBytes<64>, { let one = C::Base::ONE; + let a = C::a(); + let b = C::b(); // 1. tv1 = u^2 let tv1 = u.square(); @@ -176,7 +175,7 @@ where /// Implementation of https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-16.html#name-shallue-van-de-woestijne-met #[allow(clippy::type_complexity)] -pub(crate) fn svdw_map_to_curve<'a, C>( +pub(crate) fn svdw_hash_to_curve<'a, C>( curve_id: &'static str, domain_prefix: &'a str, z: C::Base, @@ -185,14 +184,28 @@ where C: CurveExt, C::Base: FromUniformBytes<64>, { + let [c1, c2, c3, c4] = svdw_precomputed_constants::(z); + + Box::new(move |message| { + let mut us = [C::Base::ZERO; 2]; + hash_to_field("SVDW", curve_id, domain_prefix, message, &mut us); + + let [q0, q1]: [C; 2] = us.map(|u| svdw_map_to_curve(u, c1, c2, c3, c4, z)); + + let r = q0 + &q1; + debug_assert!(bool::from(r.is_on_curve())); + r + }) +} + +pub(crate) fn svdw_precomputed_constants(z: C::Base) -> [C::Base; 4] { + let a = C::a(); + let b = C::b(); let one = C::Base::ONE; let three = one + one + one; let four = three + one; - let a = C::a(); - let b = C::b(); let tmp = three * z.square() + four * a; - // Precomputed constants: // 1. c1 = g(Z) let c1 = (z.square() + a) * z + b; // 2. c2 = -Z / 2 @@ -205,14 +218,5 @@ where // 4. c4 = -4 * g(Z) / (3 * Z^2 + 4 * A) let c4 = -four * c1 * tmp.invert().unwrap(); - Box::new(move |message| { - let mut us = [C::Base::ZERO; 2]; - hash_to_field("SVDW", curve_id, domain_prefix, message, &mut us); - - let [q0, q1]: [C; 2] = us.map(|u| map_to_curve(u, &c1, c2, &c3, &c4, &a, &b, &z)); - - let r = q0 + &q1; - debug_assert!(bool::from(r.is_on_curve())); - r - }) + [c1, c2, c3, c4] } diff --git a/src/tests/curve.rs b/src/tests/curve.rs index 2573dc19..442868cc 100644 --- a/src/tests/curve.rs +++ b/src/tests/curve.rs @@ -2,8 +2,9 @@ use crate::ff::Field; use crate::group::prime::PrimeCurveAffine; +use crate::tests::fe_from_str; use crate::{group::GroupEncoding, serde::SerdeObject}; -use crate::{CurveAffine, CurveExt}; +use crate::{hash_to_curve, CurveAffine, CurveExt}; use rand_core::{OsRng, RngCore}; use std::iter; @@ -327,3 +328,18 @@ pub fn hash_to_curve_test() { assert!(bool::from(hasher(&message).is_on_curve())); } } + +pub fn svdw_map_to_curve_test( + z: G::Base, + precomputed_constants: [&'static str; 4], + test_vector: impl IntoIterator, +) { + let [c1, c2, c3, c4] = hash_to_curve::svdw_precomputed_constants::(z); + assert_eq!([c1, c2, c3, c4], precomputed_constants.map(fe_from_str)); + for (u, (x, y)) in test_vector.into_iter() { + let u = fe_from_str(u); + let expected = G::AffineExt::from_xy(fe_from_str(x), fe_from_str(y)).unwrap(); + let output = hash_to_curve::svdw_map_to_curve::(u, c1, c2, c3, c4, z).to_affine(); + assert_eq!(output, expected); + } +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index f773c8d7..5c6cd819 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,2 +1,17 @@ +use ff::PrimeField; +use num_bigint::BigUint; +use num_traits::Num; +use std::borrow::Cow; + pub mod curve; pub mod field; + +pub(crate) fn fe_from_str(string: impl AsRef) -> F { + let string = string.as_ref(); + let oct = if let Some(hex) = string.strip_prefix("0x") { + Cow::Owned(BigUint::from_str_radix(hex, 16).unwrap().to_string()) + } else { + Cow::Borrowed(string) + }; + F::from_str_vartime(&oct).unwrap() +} From 421537b53a33acd78b6e7a4b00c3b943b1be8aad Mon Sep 17 00:00:00 2001 From: han0110 Date: Wed, 21 Jun 2023 08:02:44 +0000 Subject: [PATCH 6/6] refactor: remove requirement for `nightly` in CI and fix nightly clippy --- .github/workflows/ci.yml | 25 ++++--------------------- src/bn256/fr.rs | 4 ++-- src/lib.rs | 2 -- src/secp256r1/fp.rs | 4 ++-- src/secp256r1/fq.rs | 14 ++++---------- src/tests/field.rs | 22 +++++++++++----------- 6 files changed, 23 insertions(+), 48 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69b699e4..13abb797 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,17 +13,11 @@ jobs: strategy: matrix: include: - - rust: 1.63.0 - feature: default - - rust: nightly - feature: asm - + - feature: default + - feature: asm steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 - with: - override: true - toolchain: ${{ matrix.rust }} - name: Build uses: actions-rs/cargo@v1 with: @@ -37,17 +31,11 @@ jobs: strategy: matrix: include: - - rust: 1.63.0 - feature: default - - rust: nightly - feature: asm - + - feature: default + - feature: asm steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 - with: - override: true - toolchain: ${{ matrix.rust }} - name: Test uses: actions-rs/cargo@v1 with: @@ -79,8 +67,6 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - override: true - toolchain: nightly components: clippy - name: Run clippy uses: actions-rs/cargo@v1 @@ -96,9 +82,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 - with: - override: true - toolchain: nightly - name: Bench arithmetic uses: actions-rs/cargo@v1 with: diff --git a/src/bn256/fr.rs b/src/bn256/fr.rs index 24dc55ed..9f2cda19 100644 --- a/src/bn256/fr.rs +++ b/src/bn256/fr.rs @@ -463,8 +463,8 @@ mod test { let mut rng = ark_std::test_rng(); let base = (0..repeat).map(|_| (rng.next_u32() % (1 << 16)) as u64); - let timer = start_timer!(|| format!("generate {} Bn256 scalar field elements", repeat)); - let _res: Vec<_> = base.map(|b| Fr::from(b)).collect(); + let timer = start_timer!(|| format!("generate {repeat} Bn256 scalar field elements")); + let _res: Vec<_> = base.map(Fr::from).collect(); end_timer!(timer); } diff --git a/src/lib.rs b/src/lib.rs index 0b1f537c..63d76a7f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![cfg_attr(feature = "asm", feature(asm_const))] - mod arithmetic; pub mod hash_to_curve; pub mod pairing; diff --git a/src/secp256r1/fp.rs b/src/secp256r1/fp.rs index 43ebfc6c..d351b64d 100644 --- a/src/secp256r1/fp.rs +++ b/src/secp256r1/fp.rs @@ -187,7 +187,7 @@ impl ff::Field for Fp { /// Computes the square root of this element, if it exists. fn sqrt(&self) -> CtOption { - let tmp = self.pow(&[ + let tmp = self.pow([ 0x0000000000000000, 0x0000000040000000, 0x4000000000000000, @@ -200,7 +200,7 @@ impl ff::Field for Fp { /// Computes the multiplicative inverse of this element, /// failing if the element is zero. fn invert(&self) -> CtOption { - let tmp = self.pow_vartime(&[ + let tmp = self.pow_vartime([ 0xfffffffffffffffd, 0x00000000ffffffff, 0x0000000000000000, diff --git a/src/secp256r1/fq.rs b/src/secp256r1/fq.rs index d628a96e..e28c3fe6 100644 --- a/src/secp256r1/fq.rs +++ b/src/secp256r1/fq.rs @@ -177,7 +177,7 @@ impl ff::Field for Fq { /// Computes the multiplicative inverse of this element, /// failing if the element is zero. fn invert(&self) -> CtOption { - let tmp = self.pow_vartime(&[ + let tmp = self.pow_vartime([ 0xf3b9cac2fc63254f, 0xbce6faada7179e84, 0xffffffffffffffff, @@ -214,7 +214,7 @@ impl ff::Field for Fq { 0x7fffffff8000000, ]; - ff::helpers::sqrt_tonelli_shanks(self, &tm1d2) + ff::helpers::sqrt_tonelli_shanks(self, tm1d2) } fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) { @@ -344,18 +344,12 @@ mod test { #[test] fn test_delta() { - assert_eq!( - Fq::DELTA, - Fq::MULTIPLICATIVE_GENERATOR.pow(&[1u64 << Fq::S, 0, 0, 0]) - ); + assert_eq!(Fq::DELTA, Fq::MULTIPLICATIVE_GENERATOR.pow([1u64 << Fq::S])); } #[test] fn test_root_of_unity() { - assert_eq!( - Fq::ROOT_OF_UNITY.pow_vartime(&[1 << Fq::S, 0, 0, 0]), - Fq::one() - ); + assert_eq!(Fq::ROOT_OF_UNITY.pow_vartime([1 << Fq::S]), Fq::one()); } #[test] diff --git a/src/tests/field.rs b/src/tests/field.rs index 67ff6952..a85b3f0e 100644 --- a/src/tests/field.rs +++ b/src/tests/field.rs @@ -48,7 +48,7 @@ pub fn random_field_tests(type_name: String) { } fn random_multiplication_tests(mut rng: R, type_name: String) { - let _message = format!("multiplication {}", type_name); + let _message = format!("multiplication {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let a = F::random(&mut rng); @@ -74,7 +74,7 @@ fn random_multiplication_tests(mut rng: R, type_name: Stri } fn random_addition_tests(mut rng: R, type_name: String) { - let _message = format!("addition {}", type_name); + let _message = format!("addition {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let a = F::random(&mut rng); @@ -100,7 +100,7 @@ fn random_addition_tests(mut rng: R, type_name: String) { } fn random_subtraction_tests(mut rng: R, type_name: String) { - let _message = format!("subtraction {}", type_name); + let _message = format!("subtraction {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let a = F::random(&mut rng); @@ -121,7 +121,7 @@ fn random_subtraction_tests(mut rng: R, type_name: String) } fn random_negation_tests(mut rng: R, type_name: String) { - let _message = format!("negation {}", type_name); + let _message = format!("negation {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let a = F::random(&mut rng); @@ -135,7 +135,7 @@ fn random_negation_tests(mut rng: R, type_name: String) { } fn random_doubling_tests(mut rng: R, type_name: String) { - let _message = format!("doubling {}", type_name); + let _message = format!("doubling {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let mut a = F::random(&mut rng); @@ -149,7 +149,7 @@ fn random_doubling_tests(mut rng: R, type_name: String) { } fn random_squaring_tests(mut rng: R, type_name: String) { - let _message = format!("squaring {}", type_name); + let _message = format!("squaring {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let mut a = F::random(&mut rng); @@ -165,7 +165,7 @@ fn random_squaring_tests(mut rng: R, type_name: String) { fn random_inversion_tests(mut rng: R, type_name: String) { assert!(bool::from(F::ZERO.invert().is_none())); - let _message = format!("inversion {}", type_name); + let _message = format!("inversion {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let mut a = F::random(&mut rng); @@ -178,7 +178,7 @@ fn random_inversion_tests(mut rng: R, type_name: String) { } fn random_expansion_tests(mut rng: R, type_name: String) { - let _message = format!("expansion {}", type_name); + let _message = format!("expansion {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { // Compare (a + b)(c + d) and (a*c + b*c + a*d + b*d) @@ -218,7 +218,7 @@ pub fn random_bits_tests(type_name: String) { 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5, ]); - let _message = format!("to_le_bits {}", type_name); + let _message = format!("to_le_bits {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let a = F::random(&mut rng); @@ -236,7 +236,7 @@ pub fn random_serialization_test(type_name: String) { 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5, ]); - let _message = format!("serialization with SerdeObject {}", type_name); + let _message = format!("serialization with SerdeObject {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let a = F::random(&mut rng); @@ -260,7 +260,7 @@ where 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5, ]); - let _message = format!("serialization with serde {}", type_name); + let _message = format!("serialization with serde {type_name}"); let start = start_timer!(|| _message); for _ in 0..1000000 { let a = F::random(&mut rng);