Skip to content

Commit 30b02b4

Browse files
drskalmanmmagicianPratyush
authoredJan 14, 2024
Implement Elligator2 hash-to-curve for Twisted Edwards curves (arkworks-rs#659)
* Implement Elligator2 hash to curve for Twisted Edward curves * - Update the pull request number for Elligator2 map in CHANGELOG.md - Fix fmt errors in other parts of the repo. * Remove diagnostic `println`s * Remove irrelevant comment as elligator is not based on pasta Co-authored-by: mmagician <[email protected]> * Referencing RFC9380 for hash-to-curve instead of the draft, plus comment clean up. Co-authored-by: mmagician <[email protected]> * Cite new reference for hash-to-curve Co-authored-by: mmagician <[email protected]> * Make sig0 function of elligator2 map boolean instead of 0u8, 1u8 Co-authored-by: mmagician <[email protected]> * Move parity method from `curve_maps::swu` to `curve_maps` as it is used by both swu and elligator. * Remove map-to-curve sanity checks from release build. * cargo fmt * - apply new naming convention for map2curves - rename `new` to `check_parameters` * fix the documentation for `Elligator2Map::check_parameters` * Call elements of the field `element` not `point` in SWU hash-to-curve map * Mention moving of `parity` function in breaking changes. * fmt * move \arkworks-rs#659 from pending bto features in `CHANGELOG.md` * bring back `new` and MapToCurve Object. * `cargo fmt` * Move Elligator2 pre-computatable values to `Elligator2Config` * Pre-computatable Elligator2 test example * Move Elligator2 `MapToCurve` implementation to its own folder. * Fix reference to the Elligator paper * Make elligator curve map a static object following revert of revert of arkworks-rs#679 * Remove whitespace * Stricter check on SWU parameters Co-authored-by: Marcin <[email protected]> --------- Co-authored-by: mmagician <[email protected]> Co-authored-by: Pratyush Mishra <[email protected]> Co-authored-by: Pratyush Mishra <[email protected]>
1 parent 9cb911f commit 30b02b4

File tree

9 files changed

+339
-41
lines changed

9 files changed

+339
-41
lines changed
 

‎CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
- [\#577](https://github.com/arkworks-rs/algebra/pull/577) (`ark-ff`, `ark-ec`) Add `AdditiveGroup`, a trait for additive groups (equipped with scalar field).
88
- [\#593](https://github.com/arkworks-rs/algebra/pull/593) (`ark-ec`) Change `AffineRepr::xy()` to return owned values.
99
- [\#633](https://github.com/arkworks-rs/algebra/pull/633) (`ark-ec`) Generic pairing implementation for the curves from the BW6 family.
10+
- [\#659](https://github.com/arkworks-rs/algebra/pull/659) (`ark-ec`) Move auxiliary `parity` function from `ark_ec::hashing::curve_maps::swu` to `ark_ec::hashing::curve_maps`.
1011
- [\#748](https://github.com/arkworks-rs/algebra/pull/748) (`ark-ff`) Add `FromStr` for `BigInteger`.
1112

1213
### Features
1314

15+
- [\#659](https://github.com/arkworks-rs/algebra/pull/659) (`ark-ec`) Add Elligator2 hash-to-curve map.
1416
- [\#689](https://github.com/arkworks-rs/algebra/pull/689) (`ark-serialize`) Add `CanonicalSerialize` and `CanonicalDeserialize` impls for `VecDeque` and `LinkedList`.
1517
- [\#691](https://github.com/arkworks-rs/algebra/pull/691) (`ark-poly`) Implement `Polynomial` for `SparseMultilinearExtension` and `DenseMultilinearExtension`.
1618
- [\#693](https://github.com/arkworks-rs/algebra/pull/693) (`ark-serialize`) Add `serialize_to_vec!` convenience macro.
+295
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
use crate::models::twisted_edwards::{MontCurveConfig, TECurveConfig};
2+
use ark_ff::{Field, One, Zero};
3+
use core::marker::PhantomData;
4+
5+
use crate::{
6+
hashing::{curve_maps::parity, map_to_curve_hasher::MapToCurve, HashToCurveError},
7+
models::twisted_edwards::{Affine, Projective},
8+
};
9+
10+
/// Trait defining the necessary parameters for the Elligator2 hash-to-curve method
11+
/// for twisted edwards curves form of:
12+
/// `b * y² = x³ + a * x² + x`
13+
/// from [\[BHKL13\]], according to [\[HSSWW23\]]
14+
///
15+
/// - [\[BHKL13\]] <http://dx.doi.org/10.1145/2508859.2516734>
16+
/// - [\[HSSWW23\]] <https://datatracker.ietf.org/doc/html/rfc9380>
17+
pub trait Elligator2Config: TECurveConfig + MontCurveConfig {
18+
/// An element of the base field that is not a square root see \[BHKL13, Section 5\].
19+
/// When `BaseField` is a prime field, [\[HSSWW23\]] mandates that `Z` is the
20+
/// non-square with lowest absolute value in the `BaseField` when its elements
21+
/// are represented as [-(q-1)/2, (q-1)/2]
22+
const Z: Self::BaseField;
23+
24+
/// This must be equal to 1/(MontCurveConfig::COEFF_B)^2;
25+
const ONE_OVER_COEFF_B_SQUARE: Self::BaseField;
26+
27+
/// This must be equal to MontCurveConfig::COEFF_A/MontCurveConfig::COEFF_B;
28+
const COEFF_A_OVER_COEFF_B: Self::BaseField;
29+
}
30+
31+
/// Represents the Elligator2 hash-to-curve map defined by `P`.
32+
pub struct Elligator2Map<P: TECurveConfig>(PhantomData<fn() -> P>);
33+
34+
impl<P: Elligator2Config> MapToCurve<Projective<P>> for Elligator2Map<P> {
35+
/// Checks if `P` represents a valid Elligator2 map. Panics otherwise.
36+
fn check_parameters() -> Result<(), HashToCurveError> {
37+
// We assume that the Montgomery curve is correct and as such we do
38+
// not verify the prerequisite for applicability of Elligator2 map to the TECurveConfing.
39+
40+
// Verifying that Z is a non-square
41+
debug_assert!(
42+
!P::Z.legendre().is_qr(),
43+
"Z should be a quadratic non-residue for the Elligator2 map"
44+
);
45+
46+
debug_assert_eq!(
47+
P::ONE_OVER_COEFF_B_SQUARE,
48+
<P as MontCurveConfig>::COEFF_B
49+
.square()
50+
.inverse()
51+
.expect("B coefficient cannot be zero in Montgomery form"),
52+
"ONE_OVER_COEFF_B_SQUARE is not equal to 1/COEFF_B^2 in Montgomery form"
53+
);
54+
55+
debug_assert_eq!(
56+
P::COEFF_A_OVER_COEFF_B,
57+
<P as MontCurveConfig>::COEFF_A / <P as MontCurveConfig>::COEFF_B,
58+
"COEFF_A_OVER_COEFF_B is not equal to COEFF_A/COEFF_B in Montgomery form"
59+
);
60+
Ok(())
61+
}
62+
63+
/// Map an arbitrary base field element `element` to a curve point.
64+
fn map_to_curve(element: P::BaseField) -> Result<Affine<P>, HashToCurveError> {
65+
// 1. x1 = -(J / K) * inv0(1 + Z * u^2)
66+
// 2. If x1 == 0, set x1 = -(J / K)
67+
// 3. gx1 = x1^3 + (J / K) * x1^2 + x1 / K^2
68+
// 4. x2 = -x1 - (J / K)
69+
// 5. gx2 = x2^3 + (J / K) * x2^2 + x2 / K^2
70+
// 6. If is_square(gx1), set x = x1, y = sqrt(gx1) with sgn0(y) == 1.
71+
// 7. Else set x = x2, y = sqrt(gx2) with sgn0(y) == 0.
72+
// 8. s = x * K
73+
// 9. t = y * K
74+
// 10. return (s, t)
75+
76+
// ark a is irtf J
77+
// ark b is irtf k
78+
let k = <P as MontCurveConfig>::COEFF_B;
79+
let j_on_k = P::COEFF_A_OVER_COEFF_B;
80+
let ksq_inv = P::ONE_OVER_COEFF_B_SQUARE;
81+
82+
let den_1 = <P::BaseField as One>::one() + P::Z * element.square();
83+
84+
let x1 = -j_on_k
85+
/ (if den_1.is_zero() {
86+
<P::BaseField as One>::one()
87+
} else {
88+
den_1
89+
});
90+
let x1sq = x1.square();
91+
let x1cb = x1sq * x1;
92+
let gx1 = x1cb + j_on_k * x1sq + x1 * ksq_inv;
93+
94+
let x2 = -x1 - j_on_k;
95+
let x2sq = x2.square();
96+
let x2cb = x2sq * x2;
97+
let gx2 = x2cb + j_on_k * x2sq + x2 * ksq_inv;
98+
99+
let (x, mut y, sgn0) = if gx1.legendre().is_qr() {
100+
(
101+
x1,
102+
gx1.sqrt()
103+
.expect("We have checked that gx1 is a quadratic residue. Q.E.D"),
104+
true,
105+
)
106+
} else {
107+
(
108+
x2,
109+
gx2.sqrt()
110+
.expect("gx2 is a quadratic residue because gx1 is not. Q.E.D"),
111+
false,
112+
)
113+
};
114+
115+
if parity(&y) != sgn0 {
116+
y = -y;
117+
}
118+
119+
let s = x * k;
120+
let t = y * k;
121+
122+
// `(s, t)` is an affine point on the Montgomery curve.
123+
// Ideally, the TECurve would come with a mapping to its Montgomery curve,
124+
// so we could just call that mapping here.
125+
// This is currently not supported in arkworks, so
126+
// we just implement the rational map here from [\[HSSWW23\]] Appendix D
127+
128+
let tv1 = s + <P::BaseField as One>::one();
129+
let tv2 = tv1 * t;
130+
let (v, w) = if tv2.is_zero() {
131+
(<P::BaseField as Zero>::zero(), <P::BaseField as One>::one())
132+
} else {
133+
let tv2_inv = tv2
134+
.inverse()
135+
.expect("None zero element has inverse. Q.E.D.");
136+
let v = tv2_inv * tv1 * s;
137+
let w = tv2_inv * t * (s - <P::BaseField as One>::one());
138+
(v, w)
139+
};
140+
141+
let point_on_curve = Affine::<P>::new_unchecked(v, w);
142+
debug_assert!(
143+
point_on_curve.is_on_curve(),
144+
"Elligator2 mapped to a point off the curve"
145+
);
146+
Ok(point_on_curve)
147+
}
148+
}
149+
150+
#[cfg(test)]
151+
mod test {
152+
use crate::{
153+
hashing::{map_to_curve_hasher::MapToCurveBasedHasher, HashToCurve},
154+
CurveConfig,
155+
};
156+
use ark_ff::field_hashers::DefaultFieldHasher;
157+
use ark_std::vec::Vec;
158+
159+
use super::*;
160+
use ark_ff::{fields::Fp64, MontBackend, MontFp};
161+
use hashbrown::HashMap;
162+
use sha2::Sha256;
163+
164+
#[derive(ark_ff::MontConfig)]
165+
#[modulus = "101"]
166+
#[generator = "2"]
167+
pub struct F101Config;
168+
pub type F101 = Fp64<MontBackend<F101Config, 1>>;
169+
170+
#[derive(ark_ff::MontConfig)]
171+
#[modulus = "11"]
172+
#[generator = "2"]
173+
pub struct F11Config;
174+
pub type F11 = Fp64<MontBackend<F11Config, 1>>;
175+
176+
struct TestElligator2MapToCurveConfig;
177+
178+
impl CurveConfig for TestElligator2MapToCurveConfig {
179+
const COFACTOR: &'static [u64] = &[8];
180+
181+
#[rustfmt::skip]
182+
const COFACTOR_INV: F11 = MontFp!("7");
183+
184+
type BaseField = F101;
185+
type ScalarField = F11;
186+
}
187+
188+
/// sage: EnsureValidEdwards(F101,-1,12)
189+
/// sage: Curve_EdwardsToMontgomery(F101, -1, 12)
190+
/// (76, 23)
191+
/// sage: Curve_EdwardsToWeierstrass(F101, -1, 12)
192+
/// (11, 5)
193+
/// sage: EllipticCurve(F101,[11,5])
194+
/// Elliptic Curve defined by y^2 = x^3 + 11*x + 5 over Finite Field of size 101
195+
/// sage: EW = EllipticCurve(F101,[11,5])
196+
/// sage: EW.order().factor()
197+
/// 2^3 * 11
198+
/// sage: EW = EdwardsCurve(F101,-1,12)
199+
/// sage: EW.gens()[0] * 8
200+
/// (5 : 36 : 1)
201+
/// Point_WeierstrassToEdwards(F101, 11, 5, F101(5), F101(36), a_given=-1, d_given=12)
202+
/// (23, 24)
203+
impl TECurveConfig for TestElligator2MapToCurveConfig {
204+
/// COEFF_A = -1
205+
const COEFF_A: F101 = MontFp!("-1");
206+
207+
/// COEFF_D = 12
208+
const COEFF_D: F101 = MontFp!("12");
209+
210+
const GENERATOR: Affine<TestElligator2MapToCurveConfig> =
211+
Affine::<TestElligator2MapToCurveConfig>::new_unchecked(MontFp!("23"), MontFp!("24"));
212+
213+
type MontCurveConfig = TestElligator2MapToCurveConfig;
214+
}
215+
216+
impl MontCurveConfig for TestElligator2MapToCurveConfig {
217+
/// COEFF_A = 76
218+
const COEFF_A: F101 = MontFp!("76");
219+
220+
/// COEFF_B = 23
221+
const COEFF_B: F101 = MontFp!("23");
222+
223+
type TECurveConfig = TestElligator2MapToCurveConfig;
224+
}
225+
226+
/// sage: find_z_ell2(F101)
227+
/// 2
228+
/// sage: F101 = FiniteField(101)
229+
/// sage: 1/F101("23")^2
230+
/// 80
231+
/// sage: F101("76")/F101("23")
232+
/// 56
233+
impl Elligator2Config for TestElligator2MapToCurveConfig {
234+
const Z: F101 = MontFp!("2");
235+
const ONE_OVER_COEFF_B_SQUARE: F101 = MontFp!("80");
236+
237+
const COEFF_A_OVER_COEFF_B: F101 = MontFp!("56");
238+
}
239+
240+
/// The point of the test is to get a simple twisted edwards curve and make
241+
/// simple hash
242+
#[test]
243+
fn hash_arbitary_string_to_curve_elligator2() {
244+
let test_elligator2_to_curve_hasher = MapToCurveBasedHasher::<
245+
Projective<TestElligator2MapToCurveConfig>,
246+
DefaultFieldHasher<Sha256, 128>,
247+
Elligator2Map<TestElligator2MapToCurveConfig>,
248+
>::new(&[1])
249+
.unwrap();
250+
251+
let hash_result = test_elligator2_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve");
252+
253+
assert!(
254+
hash_result.is_on_curve(),
255+
"hash results into a point off the curve"
256+
);
257+
}
258+
259+
/// Use a simple twisted edwards curve and map the whole field to it. We observe
260+
/// the map behaviour. Specifically, the map should be non-constant, all
261+
/// elements should be mapped to curve successfully. everything can be mapped
262+
#[test]
263+
fn map_field_to_curve_elligator2() {
264+
Elligator2Map::<TestElligator2MapToCurveConfig>::check_parameters().unwrap();
265+
266+
let mut map_range: Vec<Affine<TestElligator2MapToCurveConfig>> = vec![];
267+
// We are mapping all elemnts of the field to the curve, verifying that
268+
// map is not constant on that set.
269+
for current_field_element in 0..101 {
270+
map_range.push(
271+
Elligator2Map::<TestElligator2MapToCurveConfig>::map_to_curve(F101::from(
272+
current_field_element as u64,
273+
))
274+
.unwrap(),
275+
);
276+
}
277+
278+
let mut counts = HashMap::new();
279+
280+
let mode = map_range
281+
.iter()
282+
.copied()
283+
.max_by_key(|&n| {
284+
let count = counts.entry(n).or_insert(0);
285+
*count += 1;
286+
*count
287+
})
288+
.unwrap();
289+
290+
assert!(
291+
*counts.get(&mode).unwrap() != 101,
292+
"a constant hash function is not good."
293+
);
294+
}
295+
}

‎ec/src/hashing/curve_maps/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
1+
use ark_ff::{BigInteger, Field, PrimeField, Zero};
2+
pub mod elligator2;
13
pub mod swu;
24
pub mod wb;
5+
6+
//// parity method on the Field elements based on [\[1\]] Section 4.1
7+
//// which is used by multiple curve maps including Elligator2 and SWU
8+
/// - [\[1\]] <https://datatracker.ietf.org/doc/html/rfc9380/>
9+
pub fn parity<F: Field>(element: &F) -> bool {
10+
element
11+
.to_base_prime_field_elements()
12+
.find(|&x| !x.is_zero())
13+
.map_or(false, |x| x.into_bigint().is_odd())
14+
}

‎ec/src/hashing/curve_maps/swu.rs

+20-29
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use crate::models::short_weierstrass::SWCurveConfig;
2-
use ark_ff::{BigInteger, Field, One, PrimeField, Zero};
3-
use ark_std::string::ToString;
2+
use ark_ff::{Field, One, Zero};
43
use core::marker::PhantomData;
54

65
use crate::{
7-
hashing::{map_to_curve_hasher::MapToCurve, HashToCurveError},
6+
hashing::{curve_maps::parity, map_to_curve_hasher::MapToCurve, HashToCurveError},
87
models::short_weierstrass::{Affine, Projective},
98
};
109

@@ -24,38 +23,26 @@ pub trait SWUConfig: SWCurveConfig {
2423
/// Represents the SWU hash-to-curve map defined by `P`.
2524
pub struct SWUMap<P: SWUConfig>(PhantomData<fn() -> P>);
2625

27-
/// Trait defining a parity method on the Field elements based on [\[1\]] Section 4.1
28-
///
29-
/// - [\[1\]] <https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/>
30-
pub fn parity<F: Field>(element: &F) -> bool {
31-
element
32-
.to_base_prime_field_elements()
33-
.find(|&x| !x.is_zero())
34-
.map_or(false, |x| x.into_bigint().is_odd())
35-
}
36-
3726
impl<P: SWUConfig> MapToCurve<Projective<P>> for SWUMap<P> {
3827
/// Checks if `P` represents a valid map.
3928
fn check_parameters() -> Result<(), HashToCurveError> {
4029
// Verifying that ZETA is a non-square
41-
if P::ZETA.legendre().is_qr() {
42-
return Err(HashToCurveError::MapToCurveError(
43-
"ZETA should be a quadratic non-residue for the SWU map".to_string(),
44-
));
45-
}
30+
debug_assert!(
31+
P::ZETA.legendre().is_qnr(),
32+
"ZETA should be a quadratic non-residue for the SWU map"
33+
);
4634

4735
// Verifying the prerequisite for applicability of SWU map
48-
if P::COEFF_A.is_zero() || P::COEFF_B.is_zero() {
49-
return Err(HashToCurveError::MapToCurveError("Simplified SWU requires a * b != 0 in the short Weierstrass form of y^2 = x^3 + a*x + b ".to_string()));
50-
}
36+
debug_assert!(!P::COEFF_A.is_zero() && !P::COEFF_B.is_zero(),
37+
"Simplified SWU requires a * b != 0 in the short Weierstrass form of y^2 = x^3 + a*x + b ");
5138

5239
Ok(())
5340
}
5441

5542
/// Map an arbitrary base field element to a curve point.
5643
/// Based on
5744
/// <https://github.com/zcash/pasta_curves/blob/main/src/hashtocurve.rs>.
58-
fn map_to_curve(point: P::BaseField) -> Result<Affine<P>, HashToCurveError> {
45+
fn map_to_curve(element: P::BaseField) -> Result<Affine<P>, HashToCurveError> {
5946
// 1. tv1 = inv0(Z^2 * u^4 + Z * u^2)
6047
// 2. x1 = (-B / A) * (1 + tv1)
6148
// 3. If tv1 == 0, set x1 = B / (Z * A)
@@ -80,7 +67,7 @@ impl<P: SWUConfig> MapToCurve<Projective<P>> for SWUMap<P> {
8067
let a = P::COEFF_A;
8168
let b = P::COEFF_B;
8269

83-
let zeta_u2 = P::ZETA * point.square();
70+
let zeta_u2 = P::ZETA * element.square();
8471
let ta = zeta_u2.square() + zeta_u2;
8572
let num_x1 = b * (ta + <P::BaseField as One>::one());
8673
let div = a * if ta.is_zero() { P::ZETA } else { -ta };
@@ -99,7 +86,7 @@ impl<P: SWUConfig> MapToCurve<Projective<P>> for SWUMap<P> {
9986
let gx1_square;
10087
let gx1;
10188

102-
assert!(
89+
debug_assert!(
10390
!div3.is_zero(),
10491
"we have checked that neither a or ZETA are zero. Q.E.D."
10592
);
@@ -134,14 +121,18 @@ impl<P: SWUConfig> MapToCurve<Projective<P>> for SWUMap<P> {
134121
// u^3 * y1 is a square root of gx2. Note that we don't actually need to
135122
// compute gx2.
136123

137-
let y2 = zeta_u2 * point * y1;
124+
let y2 = zeta_u2 * element * y1;
138125
let num_x = if gx1_square { num_x1 } else { num_x2 };
139126
let y = if gx1_square { y1 } else { y2 };
140127

141128
let x_affine = num_x / div;
142-
let y_affine = if parity(&y) != parity(&point) { -y } else { y };
129+
let y_affine = if parity(&y) != parity(&element) {
130+
-y
131+
} else {
132+
y
133+
};
143134
let point_on_curve = Affine::<P>::new_unchecked(x_affine, y_affine);
144-
assert!(
135+
debug_assert!(
145136
point_on_curve.is_on_curve(),
146137
"swu mapped to a point off the curve"
147138
);
@@ -260,8 +251,8 @@ mod test {
260251

261252
let mut map_range: Vec<Affine<TestSWUMapToCurveConfig>> = vec![];
262253
for current_field_element in 0..127 {
263-
let point = F127::from(current_field_element as u64);
264-
map_range.push(SWUMap::<TestSWUMapToCurveConfig>::map_to_curve(point).unwrap());
254+
let element = F127::from(current_field_element as u64);
255+
map_range.push(SWUMap::<TestSWUMapToCurveConfig>::map_to_curve(element).unwrap());
265256
}
266257

267258
let mut counts = HashMap::new();

‎ec/src/hashing/curve_maps/wb.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,8 @@ impl<P: WBConfig> MapToCurve<Projective<P>> for WBMap<P> {
8888
fn check_parameters() -> Result<(), HashToCurveError> {
8989
match P::ISOGENY_MAP.apply(P::IsogenousCurve::GENERATOR) {
9090
Ok(point_on_curve) => {
91-
if !point_on_curve.is_on_curve() {
92-
return Err(HashToCurveError::MapToCurveError(format!("the isogeny maps the generator of its domain: {} into {} which does not belong to its codomain.",P::IsogenousCurve::GENERATOR, point_on_curve)));
93-
}
91+
debug_assert!(point_on_curve.is_on_curve(),
92+
"the isogeny maps the generator of its domain: {} into {} which does not belong to its codomain.",P::IsogenousCurve::GENERATOR, point_on_curve);
9493
},
9594
Err(e) => return Err(e),
9695
}

‎ec/src/hashing/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::hashing::curve_maps::swu::parity;
1+
use crate::hashing::curve_maps::parity;
22
use ark_test_curves::bls12_381::{Fq, Fq2, Fq6};
33

44
#[test]

‎ec/src/scalar_mul/glv.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use crate::AdditiveGroup;
21
use crate::{
32
short_weierstrass::{Affine, Projective, SWCurveConfig},
4-
CurveGroup,
3+
AdditiveGroup, CurveGroup,
54
};
65
use ark_ff::{PrimeField, Zero};
76
use num_bigint::{BigInt, BigUint, Sign};

‎ec/src/scalar_mul/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ pub mod wnaf;
44
pub mod fixed_base;
55
pub mod variable_base;
66

7-
use crate::short_weierstrass::{Affine, Projective, SWCurveConfig};
8-
use crate::PrimeGroup;
7+
use crate::{
8+
short_weierstrass::{Affine, Projective, SWCurveConfig},
9+
PrimeGroup,
10+
};
911
use ark_ff::{AdditiveGroup, Zero};
1012
use ark_std::{
1113
ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign},

‎test-curves/src/lib.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
#![no_std]
22

3-
pub use ark_ff;
4-
pub use ark_ff::{fields::models::*, FftField, Field, LegendreSymbol, MontFp, PrimeField};
3+
pub use ark_ff::{self, fields::models::*, FftField, Field, LegendreSymbol, MontFp, PrimeField};
54

6-
pub use ark_ec;
7-
pub use ark_ec::*;
5+
pub use ark_ec::{self, *};
86

97
#[cfg(any(feature = "bls12_381_scalar_field", feature = "bls12_381_curve"))]
108
pub mod bls12_381;

0 commit comments

Comments
 (0)
Please sign in to comment.