diff --git a/Cargo.toml b/Cargo.toml index da6566a..15107ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,12 +13,19 @@ repository = "https://github.com/zkcrypto/jubjub" version = "0.10.0" edition = "2021" +[dependencies.arbitrary] +version = "1.3" +features = ["derive"] +optional = true + [dependencies.bitvec] version = "1" default-features = false [dependencies.bls12_381] -version = "0.8" +# upstreamed in https://github.com/zkcrypto/bls12_381/pull/138 +git = "https://github.com/heliaxdev/bls12_381.git" +rev = "d96b104d0dc035af160fd6505e967cb37a553320" default-features = false [dependencies.ff] @@ -49,6 +56,7 @@ default-features = false default = ["alloc", "bits"] alloc = ["ff/alloc", "group/alloc"] bits = ["ff/bits"] +arbitrary = ["dep:arbitrary", "bls12_381/arbitrary"] [[bench]] name = "fq_bench" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index de43b23..3eebdfe 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.56.0" +channel = "1.63.0" components = [ "clippy", "rustfmt" ] diff --git a/src/fr.rs b/src/fr.rs index 870f58e..57e4f96 100644 --- a/src/fr.rs +++ b/src/fr.rs @@ -19,6 +19,7 @@ use crate::util::{adc, mac, sbb}; // The internal representation of this type is four 64-bit unsigned // integers in little-endian order. Elements of Fr are always in // Montgomery form; i.e., Fr(a) = aR mod r, with R = 2^256. +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Clone, Copy, Eq)] pub struct Fr(pub(crate) [u64; 4]); diff --git a/src/lib.rs b/src/lib.rs index 014173a..b1cfb80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ //! //! This crate uses the `subtle` crate to perform constant-time operations. -#![no_std] +#![cfg_attr(not(feature = "arbitrary"), no_std)] // Catch documentation errors caused by code changes. #![deny(rustdoc::broken_intra_doc_links)] #![deny(missing_debug_implementations)] @@ -135,15 +135,26 @@ impl ConditionallySelectable for AffinePoint { /// * Add it to an `ExtendedPoint`, `AffineNielsPoint` or `ExtendedNielsPoint`. /// * Double it using `double()`. /// * Compare it with another extended point using `PartialEq` or `ct_eq()`. +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Clone, Copy, Debug, Eq)] pub struct ExtendedPoint { u: Fq, v: Fq, + #[cfg_attr(feature = "arbitrary", arbitrary(with = arbitrary_non_zero_fq))] z: Fq, t1: Fq, t2: Fq, } +#[cfg(feature = "arbitrary")] +fn arbitrary_non_zero_fq(u: &mut arbitrary::Unstructured) -> arbitrary::Result { + let raw: Fq = arbitrary::Arbitrary::arbitrary(u)?; + if bool::from(raw.is_zero()) { + return Err(arbitrary::Error::IncorrectFormat); + } + Ok(raw) +} + impl fmt::Display for ExtendedPoint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self) @@ -1118,6 +1129,7 @@ impl_binops_multiplicative_mixed!(AffinePoint, Fr, ExtendedPoint); /// This represents a point in the prime-order subgroup of Jubjub, in extended /// coordinates. +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct SubgroupPoint(ExtendedPoint);