diff --git a/.travis.yml b/.travis.yml index 7b3372c3..51735ca4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,14 @@ cache: cargo rust: - stable +env: + global: + - FEATURES=testing-utils + before_script: - rustup component add rustfmt-preview - cargo fmt --all -- --check script: - - cargo build --verbose - - cargo test --verbose + - cargo build --features $FEATURES --verbose + - cargo test --features $FEATURES --verbose diff --git a/Cargo.toml b/Cargo.toml index 8a79e4a7..893550e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,11 @@ repository = "https://github.com/ZenGo-X/curv" [lib] crate-type = ["lib"] +[features] +default = [] +# Exposes utils useful for testing +testing-utils = ["paste"] + [dependencies] rand = "0.6" serde = "1.0" @@ -22,6 +27,7 @@ digest = "0.8.1" hex = "^0.3" blake2b_simd = "0.5.7" derivative = "2.1.1" +paste = { version = "1.0.2", optional = true } [dependencies.rust-gmp-kzen] version = "0.5.0" diff --git a/src/cryptographic_primitives/commitments/hash_commitment.rs b/src/cryptographic_primitives/commitments/hash_commitment.rs index c70f2ab5..01f607fe 100644 --- a/src/cryptographic_primitives/commitments/hash_commitment.rs +++ b/src/cryptographic_primitives/commitments/hash_commitment.rs @@ -80,7 +80,7 @@ mod tests { let (_commitment, blind_factor) = HashCommitment::create_commitment(&message); let commitment2 = HashCommitment::create_commitment_with_user_defined_randomness(&message, &blind_factor); - assert_eq!(commitment2.to_str_radix(16).len(), SECURITY_BITS / 4); + assert!(commitment2.to_str_radix(16).len() / 2 <= SECURITY_BITS / 8); } #[test] diff --git a/src/elliptic/curves/p256.rs b/src/elliptic/curves/p256.rs index 75ea2445..de230337 100644 --- a/src/elliptic/curves/p256.rs +++ b/src/elliptic/curves/p256.rs @@ -28,7 +28,7 @@ pub struct Secp256r1Scalar { fe: SK, } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug)] pub struct Secp256r1Point { purpose: &'static str, ge: PK, @@ -228,6 +228,12 @@ impl PartialEq for Secp256r1Scalar { } } +impl PartialEq for Secp256r1Point { + fn eq(&self, other: &GE) -> bool { + self.ge == other.ge + } +} + impl Zeroize for Secp256r1Point { fn zeroize(&mut self) { unsafe { ptr::write_volatile(self, GE::generator()) }; diff --git a/src/lib.rs b/src/lib.rs index cdf391cb..6624ac81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,42 +24,114 @@ pub enum ErrorSS { VerifyShareError, } -#[cfg(test)] +/// Helps write tests generic over choice of elliptic curve +/// +/// As input it expects name of a function which takes one generic parameter: +/// curve implementation. Function restricted to have no arguments and return `()`. +/// Macro outputs several tests each one runs given function with specific curve implementation. +/// +/// ## Example +/// Suppose you have following generic test: +/// ```rust +/// # use curv::elliptic::curves::traits::*; +/// # use curv::test_for_all_curves; +/// test_for_all_curves!(test_dh); +/// fn test_dh() +/// where P: ECPoint + Clone, +/// P::Scalar: Clone, +/// { +/// let party_a_secret: P::Scalar = ECScalar::new_random(); +/// let party_a_public = P::generator() * party_a_secret.clone(); +/// +/// let party_b_secret: P::Scalar = ECScalar::new_random(); +/// let party_b_public = P::generator() * party_b_secret.clone(); +/// +/// let party_a_share = party_b_public * party_a_secret; +/// let party_b_share = party_a_public * party_b_secret; +/// +/// assert!(party_a_share == party_b_share, "Parties share expected to be the same") +/// } +/// # test_dh::(); +/// ``` +/// +/// Macro will generate this code for you: +/// ```rust +/// # use curv::elliptic::curves::traits::*; +/// # fn test_dh() { /* see code snippet above */ } +/// #[test] +/// fn test_dh_secp256k1() { +/// test_dh::() +/// } +/// #[test] +/// fn test_dh_ristretto() { +/// test_dh::() +/// } +/// #[test] +/// fn test_dh_ed25519() { +/// test_dh::() +/// } +/// #[test] +/// fn test_dh_bls12_381() { +/// test_dh::() +/// } +/// #[test] +/// fn test_dh_p256() { +/// test_dh::() +/// } +/// ``` +/// +/// ## Attributes +/// You can also pass `#[should_panic]` attribute: +/// ```rust +/// # use curv::elliptic::curves::traits::*; +/// # use curv::test_for_all_curves; +/// test_for_all_curves!(#[should_panic] failure_test); +/// fn failure_test() { /* ... */ } +/// ``` +/// +/// This will require every produced test to panic. +#[cfg(any(test, feature = "testing-utils"))] +#[cfg_attr(docsrs, doc(cfg(feature = "testing-utils")))] #[macro_export] macro_rules! test_for_all_curves { (#[should_panic] $fn: ident) => { - crate::test_for_all_curves!([#[should_panic]] $fn); + $crate::test_for_all_curves!([#[should_panic]] $fn); }; ($fn: ident) => { - crate::test_for_all_curves!([] $fn); + $crate::test_for_all_curves!([] $fn); }; ([$($attrs:tt)*] $fn: ident) => { - paste::paste!{ + $crate::paste!{ #[test] $($attrs)* fn [<$fn _secp256k1>]() { - $fn::() + $fn::<$crate::elliptic::curves::secp256_k1::GE>() } #[test] $($attrs)* fn [<$fn _ristretto>]() { - $fn::() + $fn::<$crate::elliptic::curves::curve_ristretto::GE>() } #[test] $($attrs)* fn [<$fn _ed25519>]() { - $fn::() + $fn::<$crate::elliptic::curves::ed25519::GE>() } #[test] $($attrs)* fn [<$fn _bls12_381>]() { - $fn::() + $fn::<$crate::elliptic::curves::bls12_381::GE>() } #[test] $($attrs)* fn [<$fn _p256>]() { - $fn::() + $fn::<$crate::elliptic::curves::p256::GE>() } } }; } + +/// Re-exporting macro to use in `test_for_all_curves!` +#[cfg(any(test, feature = "testing-utils"))] +#[doc(hidden)] +pub use paste::paste;