diff --git a/Cargo.toml b/Cargo.toml index ec4a8f0..7e85469 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ std = ["alloc", "tracing/std", "anyhow/std", "tracing-subscriber/std", "zeroize/ parallel = ["ark-ff/parallel", "ark-ec/parallel", "ark-groth16/parallel", "ark-std/parallel", "ark-r1cs-std/parallel"] # TODO: eventually, feature-gate all arkworks deps behind this feature. arkworks = ["std", "ark-std", "ark-ec", "ark-ff", "ark-serialize", "ark-bls12-377", "ark-ed-on-bls12-377"] -r1cs = ["ark-groth16", "ark-r1cs-std", "ark-relations", "ark-snark"] +r1cs = ["arkworks", "ark-groth16", "ark-r1cs-std", "ark-relations", "ark-snark"] u32_backend = [] [dev-dependencies] diff --git a/benches/sqrt.rs b/benches/sqrt.rs index e359a3e..306903c 100644 --- a/benches/sqrt.rs +++ b/benches/sqrt.rs @@ -17,9 +17,7 @@ fn sqrt_original(u: &Fq, v: &Fq) -> (bool, Fq) { if let Some(sqrt_uv) = uv.sqrt() { (true, sqrt_uv) } else { - let sqrt_zeta_uv = (*ZETA * uv) - .sqrt() - .expect("must be square if u/v nonsquare"); + let sqrt_zeta_uv = (ZETA * uv).sqrt().expect("must be square if u/v nonsquare"); (false, sqrt_zeta_uv) } } diff --git a/src/bls12_377.rs b/src/ark_curve/bls12_377.rs similarity index 100% rename from src/bls12_377.rs rename to src/ark_curve/bls12_377.rs diff --git a/src/constants.rs b/src/ark_curve/constants.rs similarity index 92% rename from src/constants.rs rename to src/ark_curve/constants.rs index 39bb20b..87a9aeb 100644 --- a/src/constants.rs +++ b/src/ark_curve/constants.rs @@ -17,11 +17,12 @@ fn from_ark_fr(x: ArkFr) -> Fr { } // Zeta is called QNR in the sage specification. -pub static ZETA: Lazy = Lazy::new(|| { - from_ark_fq(ark_ff::MontFp!( - "2841681278031794617739547238867782961338435681360110683443920362658525667816" - )) -}); +pub const ZETA: Fq = Fq::from_montgomery_limbs_64([ + 5947794125541564500, + 11292571455564096885, + 11814268415718120036, + 155746270000486182, +]); // Constants used for square root computation // @@ -51,7 +52,7 @@ pub static ZETA_TO_ONE_MINUS_M_DIV_TWO: Lazy = Lazy::new(|| { // G = ZETA^M // = 4732611889701835744065511820927274956354524915951001256593514693060564426294 -pub static G: Lazy = Lazy::new(|| (*ZETA).pow(*M)); +pub static G: Lazy = Lazy::new(|| ZETA.pow(*M)); // Choice of W in the square root algorithm. pub static SQRT_W: u32 = 8; diff --git a/src/ark_curve/edwards.rs b/src/ark_curve/edwards.rs new file mode 100644 index 0000000..1ec03b5 --- /dev/null +++ b/src/ark_curve/edwards.rs @@ -0,0 +1,77 @@ +use ark_ec::{ + twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig}, + CurveConfig, +}; + +use crate::ark_curve::constants::{GENERATOR_X, GENERATOR_Y}; +use crate::{Fq, Fr}; + +#[derive(Clone, Default, PartialEq, Eq)] +pub struct Decaf377EdwardsConfig; + +// These types should not be exported. They are similar to `EdwardsAffine` and +// `EdwardsProjective` from the `ark_ed_on_bls12_377` crate, except using our own +// `Decaf377Config` that has the cofactor set to 1. Consumers of this +// library should use the `AffinePoint` and `Element` (projective) +// types. +pub type EdwardsAffine = Affine; +pub type EdwardsProjective = Projective; + +impl CurveConfig for Decaf377EdwardsConfig { + type BaseField = Fq; + type ScalarField = Fr; + + const COFACTOR: &'static [u64] = &[1]; + + const COFACTOR_INV: Fr = Fr::one(); +} + +impl TECurveConfig for Decaf377EdwardsConfig { + /// COEFF_A = -1 + const COEFF_A: Fq = Fq::from_montgomery_limbs_64([ + 10157024534604021774, + 16668528035959406606, + 5322190058819395602, + 387181115924875961, + ]); + + /// COEFF_D = 3021 + const COEFF_D: Fq = Fq::from_montgomery_limbs_64([ + 15008245758212136496, + 17341409599856531410, + 648869460136961410, + 719771289660577536, + ]); + + const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y); + + type MontCurveConfig = Decaf377EdwardsConfig; + + /// Multiplication by `a` is just negation. + #[inline(always)] + fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { + -elem + } + + fn is_in_correct_subgroup_assuming_on_curve(_: &Affine) -> bool { + true + } +} + +impl MontCurveConfig for Decaf377EdwardsConfig { + const COEFF_A: Fq = Fq::from_montgomery_limbs_64([ + 13800168384327121454, + 6841573379969807446, + 12529593083398462246, + 853978956621483129, + ]); + + const COEFF_B: Fq = Fq::from_montgomery_limbs_64([ + 7239382437352637935, + 14509846070439283655, + 5083066350480839936, + 1265663645916442191, + ]); + + type TECurveConfig = Decaf377EdwardsConfig; +} diff --git a/src/element.rs b/src/ark_curve/element.rs similarity index 53% rename from src/element.rs rename to src/ark_curve/element.rs index 31aa2fe..7a61745 100644 --- a/src/element.rs +++ b/src/ark_curve/element.rs @@ -1,91 +1,18 @@ -use ark_ec::{ - twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig}, - AffineRepr, CurveConfig, CurveGroup, Group, ScalarMul, VariableBaseMSM, -}; +use ark_ec::{AffineRepr, CurveGroup, Group, ScalarMul, VariableBaseMSM}; use ark_serialize::Valid; use ark_std::vec::Vec; use crate::{ - constants::{GENERATOR_X, GENERATOR_Y}, + ark_curve::{edwards::EdwardsAffine, Decaf377EdwardsConfig, EdwardsProjective}, Fq, Fr, }; pub mod affine; pub mod projective; -pub use affine::AffineElement; +pub use affine::AffinePoint; pub use projective::Element; -#[derive(Clone, Default, PartialEq, Eq)] -pub struct Decaf377EdwardsConfig; - -// These types should not be exported. They are similar to `EdwardsAffine` and -// `EdwardsProjective` from the `ark_ed_on_bls12_377` crate, except using our own -// `Decaf377Config` that has the cofactor set to 1. Consumers of this -// library should use the `AffineElement` and `Element` (projective) -// types. -pub(crate) type EdwardsAffine = Affine; -pub(crate) type EdwardsProjective = Projective; - -impl CurveConfig for Decaf377EdwardsConfig { - type BaseField = Fq; - type ScalarField = Fr; - - const COFACTOR: &'static [u64] = &[1]; - - const COFACTOR_INV: Fr = Fr::one(); -} - -impl TECurveConfig for Decaf377EdwardsConfig { - /// COEFF_A = -1 - const COEFF_A: Fq = Fq::from_montgomery_limbs_64([ - 10157024534604021774, - 16668528035959406606, - 5322190058819395602, - 387181115924875961, - ]); - - /// COEFF_D = 3021 - const COEFF_D: Fq = Fq::from_montgomery_limbs_64([ - 15008245758212136496, - 17341409599856531410, - 648869460136961410, - 719771289660577536, - ]); - - const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y); - - type MontCurveConfig = Decaf377EdwardsConfig; - - /// Multiplication by `a` is just negation. - #[inline(always)] - fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { - -elem - } - - fn is_in_correct_subgroup_assuming_on_curve(_: &Affine) -> bool { - true - } -} - -impl MontCurveConfig for Decaf377EdwardsConfig { - const COEFF_A: Fq = Fq::from_montgomery_limbs_64([ - 13800168384327121454, - 6841573379969807446, - 12529593083398462246, - 853978956621483129, - ]); - - const COEFF_B: Fq = Fq::from_montgomery_limbs_64([ - 7239382437352637935, - 14509846070439283655, - 5083066350480839936, - 1265663645916442191, - ]); - - type TECurveConfig = Decaf377EdwardsConfig; -} - impl Valid for Element { fn check(&self) -> Result<(), ark_serialize::SerializationError> { Ok(()) @@ -93,7 +20,7 @@ impl Valid for Element { } impl ScalarMul for Element { - type MulBase = AffineElement; + type MulBase = AffinePoint; const NEGATION_IS_CHEAP: bool = true; @@ -102,7 +29,7 @@ impl ScalarMul for Element { let result = EdwardsProjective::batch_convert_to_mul_base(&bases_inner[..]); result .into_iter() - .map(|g| AffineElement { inner: g }) + .map(|g| AffinePoint { inner: g }) .collect::>() } } @@ -137,19 +64,19 @@ impl CurveGroup for Element { type BaseField = Fq; - type Affine = AffineElement; + type Affine = AffinePoint; // This type is supposed to represent an element of the entire elliptic // curve group, not just the prime-order subgroup. Since this is decaf, // this is just an `Element` again. - type FullGroup = AffineElement; + type FullGroup = AffinePoint; - fn normalize_batch(v: &[Self]) -> Vec { + fn normalize_batch(v: &[Self]) -> Vec { let v_inner = v.iter().map(|g| g.inner).collect::>(); let result = EdwardsProjective::normalize_batch(&v_inner[..]); result .into_iter() - .map(|g| AffineElement { inner: g }) + .map(|g| AffinePoint { inner: g }) .collect::>() } @@ -158,13 +85,13 @@ impl CurveGroup for Element { } } -impl Valid for AffineElement { +impl Valid for AffinePoint { fn check(&self) -> Result<(), ark_serialize::SerializationError> { Ok(()) } } -impl AffineRepr for AffineElement { +impl AffineRepr for AffinePoint { type Config = Decaf377EdwardsConfig; type ScalarField = Fr; @@ -178,7 +105,7 @@ impl AffineRepr for AffineElement { } fn zero() -> Self { - AffineElement { + AffinePoint { inner: EdwardsAffine::zero(), } } @@ -188,7 +115,7 @@ impl AffineRepr for AffineElement { } fn from_random_bytes(bytes: &[u8]) -> Option { - EdwardsAffine::from_random_bytes(bytes).map(|inner| AffineElement { inner }) + EdwardsAffine::from_random_bytes(bytes).map(|inner| AffinePoint { inner }) } fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self::Group { @@ -207,7 +134,7 @@ impl AffineRepr for AffineElement { } } -impl From for AffineElement { +impl From for AffinePoint { fn from(point: Element) -> Self { Self { inner: point.inner.into(), @@ -215,15 +142,15 @@ impl From for AffineElement { } } -impl From for Element { - fn from(point: AffineElement) -> Self { +impl From for Element { + fn from(point: AffinePoint) -> Self { Self { inner: point.inner.into(), } } } -impl From<&Element> for AffineElement { +impl From<&Element> for AffinePoint { fn from(point: &Element) -> Self { Self { inner: point.inner.into(), @@ -231,8 +158,8 @@ impl From<&Element> for AffineElement { } } -impl From<&AffineElement> for Element { - fn from(point: &AffineElement) -> Self { +impl From<&AffinePoint> for Element { + fn from(point: &AffinePoint) -> Self { Self { inner: point.inner.into(), } diff --git a/src/element/affine.rs b/src/ark_curve/element/affine.rs similarity index 62% rename from src/element/affine.rs rename to src/ark_curve/element/affine.rs index bfb8cb9..4f6fb85 100644 --- a/src/element/affine.rs +++ b/src/ark_curve/element/affine.rs @@ -1,6 +1,6 @@ use core::hash::Hash; -use crate::element::EdwardsAffine; +use crate::ark_curve::element::EdwardsAffine; use ark_std::fmt::{Display, Formatter, Result as FmtResult}; use ark_std::Zero; @@ -9,65 +9,65 @@ use zeroize::Zeroize; use crate::Element; #[derive(Copy, Clone)] -pub struct AffineElement { +pub struct AffinePoint { pub(crate) inner: EdwardsAffine, } -impl Hash for AffineElement { +impl Hash for AffinePoint { fn hash(&self, state: &mut H) { self.inner.hash(state); } } -impl Default for AffineElement { +impl Default for AffinePoint { fn default() -> Self { Element::default().into() } } -impl core::iter::Sum for Element { - fn sum>(iter: I) -> Self { +impl core::iter::Sum for Element { + fn sum>(iter: I) -> Self { iter.fold(Self::zero(), core::ops::Add::add) } } -impl<'a> core::iter::Sum<&'a AffineElement> for Element { - fn sum>(iter: I) -> Self { +impl<'a> core::iter::Sum<&'a AffinePoint> for Element { + fn sum>(iter: I) -> Self { iter.fold(Self::zero(), core::ops::Add::add) } } -impl PartialEq for AffineElement { - fn eq(&self, other: &AffineElement) -> bool { +impl PartialEq for AffinePoint { + fn eq(&self, other: &AffinePoint) -> bool { // Section 4.5 of Decaf paper self.inner.x * other.inner.y == self.inner.y * other.inner.x } } -impl Eq for AffineElement {} +impl Eq for AffinePoint {} -impl core::fmt::Debug for AffineElement { +impl core::fmt::Debug for AffinePoint { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let element: Element = self.into(); f.write_fmt(format_args!( - "decaf377::AffineElement({})", + "decaf377::AffinePoint({})", hex::encode(&element.vartime_compress().0[..]) )) } } -impl Display for AffineElement { +impl Display for AffinePoint { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { let element: Element = self.into(); write!( f, - "decaf377::AffineElement({})", + "decaf377::AffinePoint({})", hex::encode(&element.vartime_compress().0[..]) ) } } -impl Zeroize for AffineElement { +impl Zeroize for AffinePoint { fn zeroize(&mut self) { self.inner.zeroize() } diff --git a/src/element/projective.rs b/src/ark_curve/element/projective.rs similarity index 98% rename from src/element/projective.rs rename to src/ark_curve/element/projective.rs index cfdcef6..9a65221 100644 --- a/src/element/projective.rs +++ b/src/ark_curve/element/projective.rs @@ -6,7 +6,7 @@ use ark_std::fmt::{Display, Formatter, Result as FmtResult}; use zeroize::Zeroize; -use crate::{EdwardsProjective, Fq, Fr}; +use crate::{ark_curve::EdwardsProjective, Fq, Fr}; #[derive(Copy, Clone)] pub struct Element { diff --git a/src/elligator.rs b/src/ark_curve/elligator.rs similarity index 94% rename from src/elligator.rs rename to src/ark_curve/elligator.rs index c4f1f58..bb72d97 100644 --- a/src/elligator.rs +++ b/src/ark_curve/elligator.rs @@ -1,12 +1,13 @@ #![allow(non_snake_case)] use ark_ec::twisted_edwards::TECurveConfig; -use crate::element::{Decaf377EdwardsConfig, EdwardsProjective}; +use crate::ark_curve::edwards::{Decaf377EdwardsConfig, EdwardsProjective}; use crate::{ - constants::{ONE, TWO, ZETA}, + ark_curve::constants::{ONE, TWO, ZETA}, + ark_curve::on_curve::OnCurve, sign::Sign, - Element, Fq, OnCurve, + Element, Fq, }; impl Element { @@ -16,7 +17,7 @@ impl Element { let A = Decaf377EdwardsConfig::COEFF_A; let D = Decaf377EdwardsConfig::COEFF_D; - let r = *ZETA * r_0.square(); + let r = ZETA * r_0.square(); let den = (D * r - (D - A)) * ((D - A) * r - D); let num = (r + *ONE) * (A - *TWO * D); @@ -77,7 +78,7 @@ impl Element { #[cfg(test)] mod tests { - use crate::element::EdwardsAffine; + use crate::ark_curve::edwards::EdwardsAffine; use super::*; @@ -194,8 +195,8 @@ mod tests { let expected: Element = Element { inner: EdwardsAffine::new( - crate::constants::from_ark_fq(expected_xy_coordinates[ind][0]), - crate::constants::from_ark_fq(expected_xy_coordinates[ind][1]), + crate::ark_curve::constants::from_ark_fq(expected_xy_coordinates[ind][0]), + crate::ark_curve::constants::from_ark_fq(expected_xy_coordinates[ind][1]), ) .into(), }; diff --git a/src/encoding.rs b/src/ark_curve/encoding.rs similarity index 97% rename from src/encoding.rs rename to src/ark_curve/encoding.rs index 925934f..f8c4780 100644 --- a/src/encoding.rs +++ b/src/ark_curve/encoding.rs @@ -5,10 +5,11 @@ use core::convert::{TryFrom, TryInto}; use ark_ec::twisted_edwards::TECurveConfig; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, Write}; -use crate::{ - constants::TWO, element::Decaf377EdwardsConfig, sign::Sign, EdwardsProjective, Element, - EncodingError, Fq, OnCurve, +use crate::ark_curve::{ + constants::TWO, edwards::Decaf377EdwardsConfig, on_curve::OnCurve, EdwardsProjective, Element, }; +use crate::sign::Sign; +use crate::{EncodingError, Fq}; #[derive(Copy, Clone, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct Encoding(pub [u8; 32]); diff --git a/src/invsqrt.rs b/src/ark_curve/invsqrt.rs similarity index 97% rename from src/invsqrt.rs rename to src/ark_curve/invsqrt.rs index dc1af38..39eff42 100644 --- a/src/invsqrt.rs +++ b/src/ark_curve/invsqrt.rs @@ -7,7 +7,9 @@ use ark_std::boxed::Box; use ark_std::vec::Vec; use once_cell::sync::Lazy; -use crate::constants::{G, M_MINUS_ONE_DIV_TWO, N, ONE, SQRT_W, ZETA_TO_ONE_MINUS_M_DIV_TWO}; +use crate::ark_curve::constants::{ + G, M_MINUS_ONE_DIV_TWO, N, ONE, SQRT_W, ZETA_TO_ONE_MINUS_M_DIV_TWO, +}; struct SquareRootTables { pub s_lookup: HashMap, @@ -167,7 +169,7 @@ impl Fq { #[cfg(test)] mod tests { use super::*; - use crate::constants::ZETA; + use crate::ark_curve::constants::ZETA; use ark_ff::PrimeField; use proptest::prelude::*; @@ -194,7 +196,7 @@ mod tests { assert_eq!(u, v * zeta_uv); } else { // check zeta_uv = zeta * u / v - assert_eq!(*ZETA * u, v * zeta_uv); + assert_eq!(ZETA * u, v * zeta_uv); } } } diff --git a/src/ark_curve/mod.rs b/src/ark_curve/mod.rs new file mode 100644 index 0000000..aa347e0 --- /dev/null +++ b/src/ark_curve/mod.rs @@ -0,0 +1,35 @@ +pub mod bls12_377; +mod constants; +mod edwards; + +mod element; +mod elligator; +mod encoding; +mod invsqrt; +mod ops; +pub mod rand; +pub mod serialize; + +pub use constants::ZETA; +pub(crate) use edwards::{Decaf377EdwardsConfig, EdwardsProjective}; +pub use element::{AffinePoint, Element}; +pub use encoding::Encoding; + +mod on_curve; + +#[cfg(feature = "r1cs")] +pub mod r1cs; + +pub use bls12_377::Bls12_377; + +/// Return the conventional generator for `decaf377`. +pub fn basepoint() -> Element { + Element { + inner: EdwardsProjective::new( + *constants::B_X, + *constants::B_Y, + *constants::B_T, + *constants::B_Z, + ), + } +} diff --git a/src/on_curve.rs b/src/ark_curve/on_curve.rs similarity index 77% rename from src/on_curve.rs rename to src/ark_curve/on_curve.rs index 560489f..5506786 100644 --- a/src/on_curve.rs +++ b/src/ark_curve/on_curve.rs @@ -1,16 +1,11 @@ -use cfg_if::cfg_if; +use ark_ec::{ + models::{twisted_edwards::Projective, twisted_edwards::TECurveConfig}, + Group, +}; +use ark_ff::{BigInteger, Field, PrimeField, Zero}; +use ark_serialize::CanonicalSerialize; -cfg_if! { - if #[cfg(feature = "arkworks")] { - use ark_ec::{ - models::{twisted_edwards::Projective, twisted_edwards::TECurveConfig}, - Group, - }; - use ark_ff::{BigInteger, Field, PrimeField, Zero}; - use ark_serialize::CanonicalSerialize; - use crate::constants; - } -} +use crate::ark_curve::constants; pub trait OnCurve { fn is_on_curve(&self) -> bool; diff --git a/src/ops.rs b/src/ark_curve/ops.rs similarity index 100% rename from src/ops.rs rename to src/ark_curve/ops.rs diff --git a/src/ark_curve/ops/affine.rs b/src/ark_curve/ops/affine.rs new file mode 100644 index 0000000..2568170 --- /dev/null +++ b/src/ark_curve/ops/affine.rs @@ -0,0 +1,182 @@ +use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; + +use ark_ec::twisted_edwards::Projective; + +use crate::{ + ark_curve::element::AffinePoint, ark_curve::Decaf377EdwardsConfig, ark_curve::Element, Fr, +}; + +impl<'a, 'b> Add<&'b AffinePoint> for &'a AffinePoint { + type Output = AffinePoint; + + fn add(self, other: &'b AffinePoint) -> AffinePoint { + AffinePoint { + inner: (self.inner + other.inner).into(), + } + } +} + +impl<'b> Add<&'b AffinePoint> for AffinePoint { + type Output = Element; + + fn add(self, other: &'b AffinePoint) -> Element { + (&self + other).into() + } +} + +impl<'a> Add for &'a AffinePoint { + type Output = AffinePoint; + fn add(self, other: AffinePoint) -> AffinePoint { + self + &other + } +} + +impl<'b> AddAssign<&'b AffinePoint> for AffinePoint { + fn add_assign(&mut self, other: &'b AffinePoint) { + *self = AffinePoint { + inner: (self.inner + other.inner).into(), + } + } +} + +impl AddAssign for AffinePoint { + fn add_assign(&mut self, other: AffinePoint) { + *self += &other; + } +} + +impl<'a, 'b> Sub<&'b AffinePoint> for &'a AffinePoint { + type Output = AffinePoint; + + fn sub(self, other: &'b AffinePoint) -> AffinePoint { + AffinePoint { + inner: (self.inner - other.inner).into(), + } + } +} + +impl<'b> Sub<&'b AffinePoint> for AffinePoint { + type Output = AffinePoint; + + fn sub(self, other: &'b AffinePoint) -> AffinePoint { + &self - other + } +} + +impl<'a> Sub for &'a AffinePoint { + type Output = AffinePoint; + + fn sub(self, other: AffinePoint) -> AffinePoint { + self - &other + } +} + +impl Sub for AffinePoint { + type Output = AffinePoint; + + fn sub(self, other: AffinePoint) -> AffinePoint { + &self - &other + } +} + +impl<'b> SubAssign<&'b AffinePoint> for AffinePoint { + fn sub_assign(&mut self, other: &'b AffinePoint) { + *self = AffinePoint { + inner: (self.inner - other.inner).into(), + } + } +} + +impl SubAssign for AffinePoint { + fn sub_assign(&mut self, other: AffinePoint) { + *self -= &other; + } +} + +impl Neg for AffinePoint { + type Output = Self; + + fn neg(self) -> Self { + AffinePoint { inner: -self.inner } + } +} + +impl<'b> MulAssign<&'b Fr> for AffinePoint { + fn mul_assign(&mut self, point: &'b Fr) { + let mut p: Projective = self.inner.into(); + p *= *point; + *self = AffinePoint { inner: p.into() } + } +} + +impl MulAssign for AffinePoint { + fn mul_assign(&mut self, other: Fr) { + *self *= &other; + } +} + +impl<'a, 'b> Mul<&'b Fr> for &'a AffinePoint { + type Output = AffinePoint; + + fn mul(self, point: &'b Fr) -> AffinePoint { + let mut p: Projective = self.inner.into(); + p *= *point; + AffinePoint { inner: p.into() } + } +} + +impl<'a, 'b> Mul<&'b AffinePoint> for &'a Fr { + type Output = AffinePoint; + + fn mul(self, point: &'b AffinePoint) -> AffinePoint { + point * self + } +} + +impl<'b> Mul<&'b Fr> for AffinePoint { + type Output = Element; + + fn mul(self, other: &'b Fr) -> Element { + (&self * other).into() + } +} + +impl<'a> Mul for &'a AffinePoint { + type Output = AffinePoint; + + fn mul(self, other: Fr) -> AffinePoint { + self * &other + } +} + +impl Mul for AffinePoint { + type Output = Element; + + fn mul(self, other: Fr) -> Element { + (&self * &other).into() + } +} + +impl<'b> Mul<&'b AffinePoint> for Fr { + type Output = AffinePoint; + + fn mul(self, other: &'b AffinePoint) -> AffinePoint { + &self * other + } +} + +impl<'a> Mul for &'a Fr { + type Output = AffinePoint; + + fn mul(self, other: AffinePoint) -> AffinePoint { + self * &other + } +} + +impl Mul for Fr { + type Output = AffinePoint; + + fn mul(self, other: AffinePoint) -> AffinePoint { + &self * &other + } +} diff --git a/src/ops/projective.rs b/src/ark_curve/ops/projective.rs similarity index 82% rename from src/ops/projective.rs rename to src/ark_curve/ops/projective.rs index 2ec87fd..da530bc 100644 --- a/src/ops/projective.rs +++ b/src/ark_curve/ops/projective.rs @@ -1,6 +1,6 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use crate::{element::projective::Element, AffineElement, Fr}; +use crate::{ark_curve::element::projective::Element, ark_curve::AffinePoint, Fr}; impl<'a, 'b> Add<&'b Element> for &'a Element { type Output = Element; @@ -186,36 +186,36 @@ impl Mul for Fr { } } -impl<'a> Add<&'a AffineElement> for Element { +impl<'a> Add<&'a AffinePoint> for Element { type Output = Element; - fn add(self, other: &'a AffineElement) -> Element { + fn add(self, other: &'a AffinePoint) -> Element { let element_other: Element = other.into(); &self + element_other } } -impl Add for Element { +impl Add for Element { type Output = Element; - fn add(self, other: AffineElement) -> Element { + fn add(self, other: AffinePoint) -> Element { &self + &other.into() } } -impl Add for AffineElement { +impl Add for AffinePoint { // Required to be `Element` to satisfy type bounds on // `AffineRepr::Group`. type Output = Element; - fn add(self, other: AffineElement) -> Element { + fn add(self, other: AffinePoint) -> Element { let other_element: Element = other.into(); let self_element: Element = other.into(); self_element + other_element } } -impl Add for AffineElement { +impl Add for AffinePoint { type Output = Element; fn add(self, other: Element) -> Element { @@ -223,7 +223,7 @@ impl Add for AffineElement { } } -impl<'a> Add<&'a Element> for AffineElement { +impl<'a> Add<&'a Element> for AffinePoint { type Output = Element; fn add(self, other: &'a Element) -> Element { @@ -231,46 +231,46 @@ impl<'a> Add<&'a Element> for AffineElement { } } -impl<'a> AddAssign<&'a AffineElement> for Element { - fn add_assign(&mut self, other: &'a AffineElement) { +impl<'a> AddAssign<&'a AffinePoint> for Element { + fn add_assign(&mut self, other: &'a AffinePoint) { let other_element: Element = other.into(); *self += other_element; } } -impl AddAssign for Element { - fn add_assign(&mut self, other: AffineElement) { +impl AddAssign for Element { + fn add_assign(&mut self, other: AffinePoint) { *self += &other; } } -impl<'a> SubAssign<&'a AffineElement> for Element { - fn sub_assign(&mut self, other: &'a AffineElement) { +impl<'a> SubAssign<&'a AffinePoint> for Element { + fn sub_assign(&mut self, other: &'a AffinePoint) { let other_element: Element = other.into(); *self -= other_element; } } -impl SubAssign for Element { - fn sub_assign(&mut self, other: AffineElement) { +impl SubAssign for Element { + fn sub_assign(&mut self, other: AffinePoint) { let other_element: Element = other.into(); *self -= other_element; } } -impl<'a> Sub<&'a AffineElement> for Element { +impl<'a> Sub<&'a AffinePoint> for Element { type Output = Element; - fn sub(self, other: &'a AffineElement) -> Element { + fn sub(self, other: &'a AffinePoint) -> Element { let other_element: Element = other.into(); &self - other_element } } -impl Sub for Element { +impl Sub for Element { type Output = Element; - fn sub(self, other: AffineElement) -> Element { + fn sub(self, other: AffinePoint) -> Element { &self - &other.into() } } diff --git a/src/r1cs.rs b/src/ark_curve/r1cs.rs similarity index 100% rename from src/r1cs.rs rename to src/ark_curve/r1cs.rs diff --git a/src/r1cs/element.rs b/src/ark_curve/r1cs/element.rs similarity index 96% rename from src/r1cs/element.rs rename to src/ark_curve/r1cs/element.rs index 89ad7ec..036b4bd 100644 --- a/src/r1cs/element.rs +++ b/src/ark_curve/r1cs/element.rs @@ -6,9 +6,10 @@ use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, prelude::*, R1CSVar}; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; use ark_std::vec::Vec; -use crate::r1cs::{lazy::LazyElementVar, FqVar}; -use crate::{element::EdwardsAffine, r1cs::inner::ElementVar as InnerElementVar}; -use crate::{AffineElement, Element, Fq}; +use crate::ark_curve::r1cs::{lazy::LazyElementVar, FqVar}; +use crate::ark_curve::{edwards::EdwardsAffine, r1cs::inner::ElementVar as InnerElementVar}; +use crate::ark_curve::{AffinePoint, Element}; +use crate::Fq; use super::inner::Decaf377EdwardsVar; @@ -148,8 +149,8 @@ impl AllocVar for ElementVar { } } -impl AllocVar for ElementVar { - fn new_variable>( +impl AllocVar for ElementVar { + fn new_variable>( cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, diff --git a/src/r1cs/fqvar_ext.rs b/src/ark_curve/r1cs/fqvar_ext.rs similarity index 97% rename from src/r1cs/fqvar_ext.rs rename to src/ark_curve/r1cs/fqvar_ext.rs index f2bf009..e153987 100644 --- a/src/r1cs/fqvar_ext.rs +++ b/src/ark_curve/r1cs/fqvar_ext.rs @@ -4,7 +4,8 @@ use ark_r1cs_std::select::CondSelectGadget; use ark_r1cs_std::{R1CSVar, ToBitsGadget}; use ark_relations::r1cs::SynthesisError; -use crate::{constants::ZETA, r1cs::FqVar, Fq}; +use crate::ark_curve::{constants::ZETA, r1cs::FqVar}; +use crate::Fq; pub trait FqVarExtension: Sized { fn isqrt(&self) -> Result<(Boolean, FqVar), SynthesisError>; @@ -60,7 +61,7 @@ impl FqVarExtension for FqVar { y_squared_var.conditional_enforce_equal(&FqVar::zero(), &in_case_3)?; // Case 4: `(false, sqrt(zeta*num/den))` if `num` and `den` are both nonzero and `num/den` is nonsquare; - let zeta_var = FqVar::new_constant(cs, *ZETA)?; + let zeta_var = FqVar::new_constant(cs, ZETA)?; let zeta_times_one_over_den_var = zeta_var * den_var_inv; let in_case_4 = was_not_square_var.and(&den_var_is_zero.not())?; // Certify the return value y is sqrt(zeta * 1/den) diff --git a/src/r1cs/inner.rs b/src/ark_curve/r1cs/inner.rs similarity index 97% rename from src/r1cs/inner.rs rename to src/ark_curve/r1cs/inner.rs index 7b72ee4..85e8111 100644 --- a/src/r1cs/inner.rs +++ b/src/ark_curve/r1cs/inner.rs @@ -10,11 +10,11 @@ use ark_relations::ns; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; use ark_std::vec::Vec; -use crate::element::EdwardsAffine; -use crate::Decaf377EdwardsConfig; -use crate::{ - constants::ZETA, r1cs::fqvar_ext::FqVarExtension, r1cs::FqVar, AffineElement, Element, Fq, +use crate::ark_curve::{ + constants::ZETA, edwards::EdwardsAffine, r1cs::fqvar_ext::FqVarExtension, r1cs::FqVar, + AffinePoint, Decaf377EdwardsConfig, Element, }; +use crate::Fq; pub(crate) type Decaf377EdwardsVar = AffineVar; @@ -114,7 +114,7 @@ impl ElementVar { let A_VAR = FqVar::new_constant(cs.clone(), Decaf377EdwardsConfig::COEFF_A)?; let D_VAR = FqVar::new_constant(cs.clone(), Decaf377EdwardsConfig::COEFF_D)?; - let ZETA_VAR = FqVar::new_constant(cs, *ZETA)?; + let ZETA_VAR = FqVar::new_constant(cs, ZETA)?; let r_var = ZETA_VAR * r_0_var.square()?; @@ -287,8 +287,8 @@ impl AllocVar for ElementVar { } } -impl AllocVar for ElementVar { - fn new_variable>( +impl AllocVar for ElementVar { + fn new_variable>( cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, diff --git a/src/r1cs/lazy.rs b/src/ark_curve/r1cs/lazy.rs similarity index 99% rename from src/r1cs/lazy.rs rename to src/ark_curve/r1cs/lazy.rs index 0c1d094..abb343e 100644 --- a/src/r1cs/lazy.rs +++ b/src/ark_curve/r1cs/lazy.rs @@ -3,7 +3,7 @@ use core::cell::RefCell; use ark_relations::r1cs::SynthesisError; use super::inner::ElementVar; -use crate::r1cs::FqVar; +use crate::ark_curve::r1cs::FqVar; #[derive(Clone, Debug)] pub enum Inner { diff --git a/src/r1cs/ops.rs b/src/ark_curve/r1cs/ops.rs similarity index 98% rename from src/r1cs/ops.rs rename to src/ark_curve/r1cs/ops.rs index b1ce49d..9c9f430 100644 --- a/src/r1cs/ops.rs +++ b/src/ark_curve/r1cs/ops.rs @@ -1,6 +1,6 @@ use core::ops::{Add, AddAssign, Sub, SubAssign}; -use crate::{r1cs::element::ElementVar, Element}; +use crate::ark_curve::{r1cs::element::ElementVar, Element}; use super::lazy::LazyElementVar; diff --git a/src/rand.rs b/src/ark_curve/rand.rs similarity index 81% rename from src/rand.rs rename to src/ark_curve/rand.rs index 27908f1..4ac19d2 100644 --- a/src/rand.rs +++ b/src/ark_curve/rand.rs @@ -5,7 +5,7 @@ use ark_std::rand::{ Rng, }; -use crate::{element::EdwardsProjective, AffineElement, Element, Encoding}; +use crate::ark_curve::{edwards::EdwardsProjective, AffinePoint, Element, Encoding}; impl Distribution for Standard { #[inline] @@ -26,8 +26,8 @@ impl Distribution for Standard { } } -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> AffineElement { +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> AffinePoint { let point: Element = self.sample(rng); point.into() } diff --git a/src/serialize.rs b/src/ark_curve/serialize.rs similarity index 90% rename from src/serialize.rs rename to src/ark_curve/serialize.rs index e20139a..51bec81 100644 --- a/src/serialize.rs +++ b/src/ark_curve/serialize.rs @@ -3,9 +3,9 @@ use core::convert::TryInto; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::io::{Read, Write}; -use crate::{AffineElement, Element, Encoding}; +use crate::ark_curve::{AffinePoint, Element, Encoding}; -impl CanonicalDeserialize for AffineElement { +impl CanonicalDeserialize for AffinePoint { fn deserialize_with_mode( reader: R, compress: ark_serialize::Compress, @@ -27,7 +27,7 @@ impl CanonicalDeserialize for AffineElement { } } -impl CanonicalSerialize for AffineElement { +impl CanonicalSerialize for AffinePoint { fn serialized_size(&self, compress: ark_serialize::Compress) -> usize { match compress { ark_serialize::Compress::Yes => 32, diff --git a/src/error.rs b/src/error.rs index a8261c7..3134933 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,3 @@ -use ark_std::error::Error; - #[derive(Debug)] pub enum EncodingError { InvalidEncoding, @@ -16,5 +14,3 @@ impl core::fmt::Display for EncodingError { msg.fmt(f) } } - -impl Error for EncodingError {} diff --git a/src/field_ext.rs b/src/field_ext.rs index 6f6bc2a..6636923 100644 --- a/src/field_ext.rs +++ b/src/field_ext.rs @@ -1,5 +1,3 @@ -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; - use crate::{EncodingError, Fq, Fr}; /// An extension trait for easy conversion of [`Fr`] and [`Fq`] elements to and from bytes. @@ -12,36 +10,22 @@ pub trait FieldExt: Sized { impl FieldExt for Fr { fn to_bytes(&self) -> [u8; 32] { - let mut bytes = [0u8; 32]; - debug_assert_eq!(self.serialized_size(ark_serialize::Compress::Yes), 32); - self.serialize_compressed(&mut bytes[..]) - .expect("serialization into array should be infallible"); - bytes + self.to_bytes_le() } fn from_bytes(bytes: [u8; 32]) -> Result { - Self::deserialize_compressed(&bytes[..]).map_err(|_| EncodingError::InvalidEncoding) + Fr::from_bytes_checked(&bytes).ok_or(EncodingError::InvalidEncoding) } } impl FieldExt for Fq { fn to_bytes(&self) -> [u8; 32] { - let mut bytes = [0u8; 32]; - debug_assert_eq!(self.serialized_size(ark_serialize::Compress::Yes), 32); - self.serialize_compressed(&mut bytes[..]) - .expect("serialization into array should be infallible"); + let bytes = self.to_bytes_le(); debug_assert!(bytes[31] >> 5 == 0u8); - bytes } fn from_bytes(bytes: [u8; 32]) -> Result { - // Check the top three bits of the last byte as Arkworks - // doesn't check them when deciding if an encoding is canonical. - if bytes[31] >> 5 != 0u8 { - return Err(EncodingError::InvalidEncoding); - } - - Self::deserialize_compressed(&bytes[..]).map_err(|_| EncodingError::InvalidEncoding) + Fq::from_bytes_checked(&bytes).ok_or(EncodingError::InvalidEncoding) } } diff --git a/src/fields/fr.rs b/src/fields/fr.rs index 87e8563..2898de4 100644 --- a/src/fields/fr.rs +++ b/src/fields/fr.rs @@ -24,3 +24,29 @@ cfg_if! { } } } + +impl Fr { + /// Convert bytes into an Fr element, returning None if these bytes are not already reduced. + /// + /// This means that values that cannot be produced by encoding a field element will return + /// None, enforcing canonical serialization. + pub fn from_bytes_checked(bytes: &[u8; 32]) -> Option { + let reduced = Self::from_raw_bytes(bytes); + if reduced.to_bytes_le() == *bytes { + Some(reduced) + } else { + None + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_from_bytes_checked() { + assert_eq!(Fr::from_bytes_checked(&[0; 32]), Some(Fr::zero())); + assert_eq!(Fr::from_bytes_checked(&[0xFF; 32]), None); + } +} diff --git a/src/lib.rs b/src/lib.rs index 70db8b5..31792d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,52 +5,31 @@ use cfg_if::cfg_if; pub mod fields; -pub mod smol_curve; pub use fields::{fp::Fp, fq::Fq, fr::Fr}; - +mod field_ext; +pub use field_ext::FieldExt; mod sign; -mod on_curve; -use on_curve::OnCurve; +mod error; +pub use error::EncodingError; cfg_if! { if #[cfg(feature = "arkworks")] { - pub mod bls12_377; - mod constants; - mod element; - mod elligator; - mod encoding; - mod error; - mod field_ext; - mod invsqrt; - mod ops; - pub mod rand; - pub mod serialize; - - pub use constants::ZETA; - pub use element::{AffineElement, Element}; - pub(crate) use element::{Decaf377EdwardsConfig, EdwardsProjective}; - pub use encoding::Encoding; - pub use error::EncodingError; - pub use field_ext::FieldExt; + mod ark_curve; + + pub use ark_curve::{Element, Encoding, ZETA}; + + pub use ark_curve::basepoint; + + pub use ark_curve::bls12_377::Bls12_377; #[cfg(feature = "r1cs")] - pub mod r1cs; - - pub use bls12_377::Bls12_377; - - - /// Return the conventional generator for `decaf377`. - pub fn basepoint() -> Element { - Element { - inner: EdwardsProjective::new( - *constants::B_X, - *constants::B_Y, - *constants::B_T, - *constants::B_Z, - ), - } - } + pub use ark_curve::r1cs; + + } else { + mod min_curve; + + pub use min_curve::{Element, Encoding, ZETA}; } } diff --git a/src/smol_curve/constants.rs b/src/min_curve/constants.rs similarity index 100% rename from src/smol_curve/constants.rs rename to src/min_curve/constants.rs diff --git a/src/smol_curve/element.rs b/src/min_curve/element.rs similarity index 97% rename from src/smol_curve/element.rs rename to src/min_curve/element.rs index e5fd18d..58a747b 100644 --- a/src/smol_curve/element.rs +++ b/src/min_curve/element.rs @@ -1,12 +1,8 @@ use core::ops::{Add, Neg}; use subtle::{Choice, ConditionallySelectable}; -use crate::{sign::Sign, smol_curve::constants::*, smol_curve::encoding::Encoding, Fq}; - -/// Error type for decompression -pub enum EncodingError { - InvalidEncoding, -} +use crate::EncodingError; +use crate::{min_curve::constants::*, min_curve::encoding::Encoding, sign::Sign, Fq}; /// A point on an Edwards curve. /// @@ -391,7 +387,8 @@ mod test { #[cfg(all(test, feature = "arkworks"))] mod proptests { use super::*; - use ark_ff::{BigInt, PrimeField}; + use ark_ed_on_bls12_377::Fq as ArkFq; + use ark_ff::{BigInt, BigInteger256, PrimeField}; use proptest::prelude::*; use crate::Fr; @@ -437,6 +434,10 @@ mod proptests { } } + pub(crate) fn from_ark_fq(x: ArkFq) -> Fq { + BigInteger256::from(x).into() + } + #[test] fn test_elligator() { // These are the test cases from testElligatorDeterministic in ristretto.sage @@ -548,9 +549,9 @@ mod proptests { let input_element = Fq::deserialize_compressed(&input[..]).expect("encoding of test vector is valid"); - let expected: Element = crate::smol_curve::element::Element::from_affine( - crate::constants::from_ark_fq(expected_xy_coordinates[ind][0]), - crate::constants::from_ark_fq(expected_xy_coordinates[ind][1]), + let expected: Element = crate::min_curve::element::Element::from_affine( + from_ark_fq(expected_xy_coordinates[ind][0]), + from_ark_fq(expected_xy_coordinates[ind][1]), ); let actual = Element::elligator_map(&input_element); diff --git a/src/smol_curve/encoding.rs b/src/min_curve/encoding.rs similarity index 100% rename from src/smol_curve/encoding.rs rename to src/min_curve/encoding.rs diff --git a/src/smol_curve/invsqrt.rs b/src/min_curve/invsqrt.rs similarity index 99% rename from src/smol_curve/invsqrt.rs rename to src/min_curve/invsqrt.rs index 4887348..c14ce5a 100644 --- a/src/smol_curve/invsqrt.rs +++ b/src/min_curve/invsqrt.rs @@ -2,7 +2,7 @@ use subtle::{ConditionallySelectable, ConstantTimeEq}; use crate::{fields::fq::arkworks_constants::*, Fq}; -use crate::smol_curve::constants::ZETA; +use crate::min_curve::constants::ZETA; impl Fq { /// For square elements, calculate their square root, otherwise return an undefined element. diff --git a/src/min_curve/mod.rs b/src/min_curve/mod.rs new file mode 100644 index 0000000..e1eb2e5 --- /dev/null +++ b/src/min_curve/mod.rs @@ -0,0 +1,9 @@ +mod constants; +pub mod element; +pub mod encoding; +mod invsqrt; +mod ops; + +pub use constants::ZETA; +pub use element::Element; +pub use encoding::Encoding; diff --git a/src/smol_curve/ops.rs b/src/min_curve/ops.rs similarity index 98% rename from src/smol_curve/ops.rs rename to src/min_curve/ops.rs index b6bc190..a669d18 100644 --- a/src/smol_curve/ops.rs +++ b/src/min_curve/ops.rs @@ -1,6 +1,6 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use crate::{smol_curve::element::Element, Fr}; +use crate::{min_curve::element::Element, Fr}; // Element addition diff --git a/src/ops/affine.rs b/src/ops/affine.rs deleted file mode 100644 index 9de695b..0000000 --- a/src/ops/affine.rs +++ /dev/null @@ -1,180 +0,0 @@ -use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; - -use ark_ec::twisted_edwards::Projective; - -use crate::{element::AffineElement, Decaf377EdwardsConfig, Element, Fr}; - -impl<'a, 'b> Add<&'b AffineElement> for &'a AffineElement { - type Output = AffineElement; - - fn add(self, other: &'b AffineElement) -> AffineElement { - AffineElement { - inner: (self.inner + other.inner).into(), - } - } -} - -impl<'b> Add<&'b AffineElement> for AffineElement { - type Output = Element; - - fn add(self, other: &'b AffineElement) -> Element { - (&self + other).into() - } -} - -impl<'a> Add for &'a AffineElement { - type Output = AffineElement; - fn add(self, other: AffineElement) -> AffineElement { - self + &other - } -} - -impl<'b> AddAssign<&'b AffineElement> for AffineElement { - fn add_assign(&mut self, other: &'b AffineElement) { - *self = AffineElement { - inner: (self.inner + other.inner).into(), - } - } -} - -impl AddAssign for AffineElement { - fn add_assign(&mut self, other: AffineElement) { - *self += &other; - } -} - -impl<'a, 'b> Sub<&'b AffineElement> for &'a AffineElement { - type Output = AffineElement; - - fn sub(self, other: &'b AffineElement) -> AffineElement { - AffineElement { - inner: (self.inner - other.inner).into(), - } - } -} - -impl<'b> Sub<&'b AffineElement> for AffineElement { - type Output = AffineElement; - - fn sub(self, other: &'b AffineElement) -> AffineElement { - &self - other - } -} - -impl<'a> Sub for &'a AffineElement { - type Output = AffineElement; - - fn sub(self, other: AffineElement) -> AffineElement { - self - &other - } -} - -impl Sub for AffineElement { - type Output = AffineElement; - - fn sub(self, other: AffineElement) -> AffineElement { - &self - &other - } -} - -impl<'b> SubAssign<&'b AffineElement> for AffineElement { - fn sub_assign(&mut self, other: &'b AffineElement) { - *self = AffineElement { - inner: (self.inner - other.inner).into(), - } - } -} - -impl SubAssign for AffineElement { - fn sub_assign(&mut self, other: AffineElement) { - *self -= &other; - } -} - -impl Neg for AffineElement { - type Output = Self; - - fn neg(self) -> Self { - AffineElement { inner: -self.inner } - } -} - -impl<'b> MulAssign<&'b Fr> for AffineElement { - fn mul_assign(&mut self, point: &'b Fr) { - let mut p: Projective = self.inner.into(); - p *= *point; - *self = AffineElement { inner: p.into() } - } -} - -impl MulAssign for AffineElement { - fn mul_assign(&mut self, other: Fr) { - *self *= &other; - } -} - -impl<'a, 'b> Mul<&'b Fr> for &'a AffineElement { - type Output = AffineElement; - - fn mul(self, point: &'b Fr) -> AffineElement { - let mut p: Projective = self.inner.into(); - p *= *point; - AffineElement { inner: p.into() } - } -} - -impl<'a, 'b> Mul<&'b AffineElement> for &'a Fr { - type Output = AffineElement; - - fn mul(self, point: &'b AffineElement) -> AffineElement { - point * self - } -} - -impl<'b> Mul<&'b Fr> for AffineElement { - type Output = Element; - - fn mul(self, other: &'b Fr) -> Element { - (&self * other).into() - } -} - -impl<'a> Mul for &'a AffineElement { - type Output = AffineElement; - - fn mul(self, other: Fr) -> AffineElement { - self * &other - } -} - -impl Mul for AffineElement { - type Output = Element; - - fn mul(self, other: Fr) -> Element { - (&self * &other).into() - } -} - -impl<'b> Mul<&'b AffineElement> for Fr { - type Output = AffineElement; - - fn mul(self, other: &'b AffineElement) -> AffineElement { - &self * other - } -} - -impl<'a> Mul for &'a Fr { - type Output = AffineElement; - - fn mul(self, other: AffineElement) -> AffineElement { - self * &other - } -} - -impl Mul for Fr { - type Output = AffineElement; - - fn mul(self, other: AffineElement) -> AffineElement { - &self * &other - } -} diff --git a/src/smol_curve/mod.rs b/src/smol_curve/mod.rs deleted file mode 100644 index a59fc74..0000000 --- a/src/smol_curve/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod constants; -pub mod element; -pub mod encoding; -mod invsqrt; -mod ops; diff --git a/tests/encoding.proptest-regressions b/tests/encoding.proptest-regressions index f5fa644..4c641e2 100644 --- a/tests/encoding.proptest-regressions +++ b/tests/encoding.proptest-regressions @@ -6,3 +6,4 @@ # everyone who runs the test benefits from these saved cases. cc 82945fc5ee2715e3e8cd35890759aefcdd76b3381f6379e26ba009933f55abd3 # shrinks to bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5] cc 264ed2b3f5cb8d69cb8ac150a1f1150a65b7a064170a52f4bba9a4d450f6369d # shrinks to bytes = [12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +cc ba572d5b5a4a03b1ab05649faff2f4251da79a38c91ee13d3fb9b54d9b0c6b32 # shrinks to bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 18] diff --git a/tests/encoding.rs b/tests/encoding.rs index 1d0c058..e0fc795 100644 --- a/tests/encoding.rs +++ b/tests/encoding.rs @@ -2,7 +2,7 @@ use core::convert::TryFrom; use proptest::prelude::*; -use decaf377::{basepoint, Element, Encoding, FieldExt, Fr}; +use decaf377::{basepoint, Element, Encoding, FieldExt, Fq, Fr}; /* #[test] @@ -102,6 +102,14 @@ proptest! { } } + #[test] + fn fq_encoding_round_trip_if_successful(bytes: [u8; 32]) { + if let Ok(x) = Fq::from_bytes(bytes) { + let bytes2 = x.to_bytes(); + assert_eq!(bytes, bytes2); + } + } + #[test] fn scalar_encoding_round_trip_if_successful(bytes: [u8; 32]) { if let Ok(x) = Fr::from_bytes(bytes) {