From 632ecc4530a05baa34585fc9975a4264065735fa Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Wed, 26 Jan 2022 10:00:35 +1100 Subject: [PATCH 1/7] Use fully qualified path for mem When building with --no-default-features the compiler emits: warning: unused import: `mem` The call site is feature gated so we either need to feature gate the import or use a fully qualified path. Since 'core' is quite short elect to use the fully qualified path. --- secp256k1-sys/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/secp256k1-sys/src/types.rs b/secp256k1-sys/src/types.rs index 630e42e..e257d43 100644 --- a/secp256k1-sys/src/types.rs +++ b/secp256k1-sys/src/types.rs @@ -1,5 +1,5 @@ #![allow(non_camel_case_types)] -use core::{fmt, mem}; +use core::fmt; pub type c_int = i32; pub type c_uchar = u8; @@ -46,7 +46,7 @@ impl AlignedType { } #[cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))] -pub(crate) const ALIGN_TO: usize = mem::align_of::(); +pub(crate) const ALIGN_TO: usize = ::core::mem::align_of::(); #[cfg(test)] mod tests { From 433c350424718d91037bb1a1db5ea175d70c63a8 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 1 Feb 2022 14:50:21 +1100 Subject: [PATCH 2/7] Add multiple implementations of Debug for secrets The `Debug` implementation for secrets is feature gated on `std` because it uses a hasher from `std`. If `bitcoin_hashes` is enabled we can use it for hashing. If neither `std` nor `bitcoin_hashes` is enabled fall back to outputting: Remove the docs conditional since we now implement `Debug` always. --- src/secret.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/secret.rs b/src/secret.rs index 28bd80d..ba61ee6 100644 --- a/src/secret.rs +++ b/src/secret.rs @@ -22,7 +22,6 @@ macro_rules! impl_display_secret { // Default hasher exists only in standard library and not alloc ($thing:ident) => { #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl ::core::fmt::Debug for $thing { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use ::core::hash::Hasher; @@ -44,6 +43,33 @@ macro_rules! impl_display_secret { .finish() } } + + #[cfg(all(not(feature = "std"), feature = "bitcoin_hashes"))] + impl ::core::fmt::Debug for $thing { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use hashes::{sha256, Hash, HashEngine}; + + let tag = "rust-secp256k1DEBUG"; + + let mut engine = sha256::Hash::engine(); + let tag_hash = sha256::Hash::hash(tag.as_bytes()); + engine.input(&tag_hash[..]); + engine.input(&tag_hash[..]); + engine.input(&self.serialize_secret()); + let hash = sha256::Hash::from_engine(engine); + + f.debug_tuple(stringify!($thing)) + .field(&format_args!("#{:016x}", hash)) + .finish() + } + } + + #[cfg(all(not(feature = "std"), not(feature = "bitcoin_hashes")))] + impl ::core::fmt::Debug for $thing { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "") + } + } } } @@ -92,6 +118,7 @@ impl SecretKey { /// # Example /// /// ``` + /// # #[cfg(all(feature = "std", not(feature = "bitcoin_hashes")))] { /// use secp256k1::ONE_KEY; /// let key = ONE_KEY; /// // Normal display hides value @@ -108,6 +135,7 @@ impl SecretKey { /// "DisplaySecret(\"0000000000000000000000000000000000000000000000000000000000000001\")", /// format!("{:?}", key.display_secret()) /// ); + /// # } /// ``` #[inline] pub fn display_secret(&self) -> DisplaySecret { @@ -125,6 +153,7 @@ impl KeyPair { /// # Example /// /// ``` + /// # #[cfg(all(feature = "std", not(feature = "bitcoin_hashes")))] { /// use secp256k1::ONE_KEY; /// use secp256k1::KeyPair; /// use secp256k1::Secp256k1; @@ -147,6 +176,8 @@ impl KeyPair { /// "DisplaySecret(\"0000000000000000000000000000000000000000000000000000000000000001\")", /// format!("{:?}", key.display_secret()) /// ); + /// # } + /// ``` #[inline] pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.serialize_secret() } From a79840eca202682d13555820d98d2e4e9747b5bc Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 1 Feb 2022 14:59:29 +1100 Subject: [PATCH 3/7] Be explicit about example feature requirements The examples depend on having the "std" feature [1]. In preparation for being able to run tests with `--no-default-features` add the "std" feature as a requirement for all three examples. While we are at it use the correct rand feature requirement: `rand-std`. [1] Technically we only need "alloc" but "alloc" is not working with Rust 1.29 currently so just use "std". --- Cargo.toml | 5 +++-- contrib/test.sh | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2db1078..bf9a231 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,14 +49,15 @@ rand = { version = "0.6", features = ["wasm-bindgen"] } [[example]] name = "sign_verify_recovery" -required-features = ["recovery"] +required-features = ["std", "recovery"] [[example]] name = "sign_verify" +required-features = ["std"] [[example]] name = "generate_keys" -required-features = ["rand"] +required-features = ["std", "rand-std"] [workspace] members = ["secp256k1-sys"] diff --git a/contrib/test.sh b/contrib/test.sh index dc936ab..d1cd935 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -45,9 +45,9 @@ if [ "$DO_FEATURE_MATRIX" = true ]; then fi # Examples - cargo run --example sign_verify - cargo run --example sign_verify_recovery --features=recovery - cargo run --example generate_keys --features=rand + cargo run --example sign_verify --features=std + cargo run --example sign_verify_recovery --features=std,recovery + cargo run --example generate_keys --features=std,rand-std fi # Docs From c01cd8f1f34e74f2dacd2094e815486a87f6d934 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 1 Feb 2022 13:43:42 +1100 Subject: [PATCH 4/7] Enable running tests without default features Currently various features fail to build when enabled without default features. This is because many tests need feature gating. Feature gating the import statements quickly turns into spaghetti when trying to cover all combinations of two features correctly, instead just allow unused imports on `tests` modules where needed. Add correct feature requirements to the examples so they also can be run without default features. Improve the CI script by doing: - Add `std` to the feature matrix. - Add `--no-default-features` to test runs in the CI script. --- contrib/test.sh | 10 ++++----- src/context.rs | 3 ++- src/ecdh.rs | 7 +++++- src/ecdsa/mod.rs | 4 ++-- src/ecdsa/recovery.rs | 6 +++++ src/key.rs | 52 ++++++++++++++++++++++++++++++------------- src/lib.rs | 24 +++++++++++++++++--- src/schnorr.rs | 32 ++++++++++++++++++++------ 8 files changed, 103 insertions(+), 35 deletions(-) diff --git a/contrib/test.sh b/contrib/test.sh index d1cd935..c79d3f8 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -1,6 +1,7 @@ #!/bin/sh -ex -FEATURES="bitcoin_hashes global-context lowmemory rand rand-std recovery serde" +# TODO: Add "alloc" once we bump MSRV to past 1.29 +FEATURES="bitcoin_hashes global-context lowmemory rand rand-std recovery serde std" # Use toolchain if explicitly specified if [ -n "$TOOLCHAIN" ] @@ -20,17 +21,16 @@ cargo test --all if [ "$DO_FEATURE_MATRIX" = true ]; then cargo build --all --no-default-features - #This doesn't work but probably should --andrew - #cargo test --all --no-default-features + cargo test --all --no-default-features # All features cargo build --all --no-default-features --features="$FEATURES" - cargo test --all --features="$FEATURES" + cargo test --all --no-default-features --features="$FEATURES" # Single features for feature in ${FEATURES} do cargo build --all --no-default-features --features="$feature" - cargo test --all --features="$feature" + cargo test --all --no-default-features --features="$feature" done # Other combos diff --git a/src/context.rs b/src/context.rs index 03caff5..f14f2cb 100644 --- a/src/context.rs +++ b/src/context.rs @@ -9,7 +9,7 @@ use Secp256k1; #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] pub use self::alloc_only::*; -#[cfg(feature = "global-context-less-secure")] +#[cfg(all(feature = "global-context-less-secure", feature = "std"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "global-context", feature = "global-context-less-secure"))))] /// Module implementing a singleton pattern for a global `Secp256k1` context pub mod global { @@ -35,6 +35,7 @@ pub mod global { impl Deref for GlobalContext { type Target = Secp256k1; + #[allow(unused_mut)] // Unused when "global-context" is not enabled. fn deref(&self) -> &Self::Target { static ONCE: Once = Once::new(); static mut CONTEXT: Option> = None; diff --git a/src/ecdh.rs b/src/ecdh.rs index de75314..1847c3c 100644 --- a/src/ecdh.rs +++ b/src/ecdh.rs @@ -127,6 +127,7 @@ impl SharedSecret { /// `SharedSecret` can be easily created via the `From` impl from arrays. /// # Examples /// ``` + /// # #[cfg(any(feature = "alloc", features = "std"))] { /// # use secp256k1::ecdh::SharedSecret; /// # use secp256k1::{Secp256k1, PublicKey, SecretKey}; /// # fn sha2(_a: &[u8], _b: &[u8]) -> [u8; 32] {[0u8; 32]} @@ -139,7 +140,7 @@ impl SharedSecret { /// let hash: [u8; 32] = sha2(&x,&y); /// hash.into() /// }); - /// + /// # } /// ``` pub fn new_with_hash(point: &PublicKey, scalar: &SecretKey, mut hash_function: F) -> SharedSecret where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret { @@ -168,6 +169,7 @@ impl SharedSecret { } #[cfg(test)] +#[allow(unused_imports)] mod tests { use super::*; use rand::thread_rng; @@ -177,6 +179,7 @@ mod tests { use wasm_bindgen_test::wasm_bindgen_test as test; #[test] + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn ecdh() { let s = Secp256k1::signing_only(); let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); @@ -190,6 +193,7 @@ mod tests { } #[test] + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn ecdh_with_hash() { let s = Secp256k1::signing_only(); let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); @@ -203,6 +207,7 @@ mod tests { } #[test] + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn ecdh_with_hash_callback() { let s = Secp256k1::signing_only(); let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); diff --git a/src/ecdsa/mod.rs b/src/ecdsa/mod.rs index 7098ab4..f7baa71 100644 --- a/src/ecdsa/mod.rs +++ b/src/ecdsa/mod.rs @@ -431,7 +431,7 @@ impl Secp256k1 { /// verify-capable context. /// /// ```rust - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] { /// # use secp256k1::rand::rngs::OsRng; /// # use secp256k1::{Secp256k1, Message, Error}; /// # @@ -460,7 +460,7 @@ impl Secp256k1 { /// verify-capable context. /// /// ```rust - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] { /// # use secp256k1::rand::rngs::OsRng; /// # use secp256k1::{Secp256k1, Message, Error}; /// # diff --git a/src/ecdsa/recovery.rs b/src/ecdsa/recovery.rs index 7d532d2..ca367de 100644 --- a/src/ecdsa/recovery.rs +++ b/src/ecdsa/recovery.rs @@ -201,6 +201,7 @@ impl Secp256k1 { #[cfg(test)] +#[allow(unused_imports)] mod tests { use super::*; use rand::{RngCore, thread_rng}; @@ -210,6 +211,7 @@ mod tests { use wasm_bindgen_test::wasm_bindgen_test as test; #[test] + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn capabilities() { let sign = Secp256k1::signing_only(); let vrfy = Secp256k1::verification_only(); @@ -243,6 +245,7 @@ mod tests { #[test] #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn sign() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -266,6 +269,7 @@ mod tests { } #[test] + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn sign_and_verify_fail() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -289,6 +293,7 @@ mod tests { } #[test] + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn sign_with_recovery() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -305,6 +310,7 @@ mod tests { } #[test] + #[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] fn bad_recovery() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); diff --git a/src/key.rs b/src/key.rs index 358eb46..9ca23d2 100644 --- a/src/key.rs +++ b/src/key.rs @@ -35,7 +35,7 @@ use ffi::{self, CPtr}; /// Basic usage: /// /// ``` -/// # #[cfg(feature="rand")] { +/// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey}; /// /// let secp = Secp256k1::new(); @@ -70,11 +70,13 @@ pub const ONE_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0, /// Basic usage: /// /// ``` +/// # #[cfg(any(feature = "alloc", feature = "std"))] { /// use secp256k1::{SecretKey, Secp256k1, PublicKey}; /// /// let secp = Secp256k1::new(); /// let secret_key = SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order"); /// let public_key = PublicKey::from_secret_key(&secp, &secret_key); +/// # } /// ``` #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[repr(transparent)] @@ -183,7 +185,7 @@ impl SecretKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair}; /// /// let secp = Secp256k1::new(); @@ -327,7 +329,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey, PublicKey}; /// /// let secp = Secp256k1::new(); @@ -375,7 +377,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, PublicKey, KeyPair}; /// /// let secp = Secp256k1::new(); @@ -506,7 +508,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1}; /// /// let secp = Secp256k1::new(); @@ -532,7 +534,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, PublicKey}; /// /// let secp = Secp256k1::new(); @@ -648,7 +650,7 @@ impl Ord for PublicKey { /// Basic usage: /// /// ``` -/// # #[cfg(feature="rand")] { +/// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, KeyPair, Secp256k1}; /// /// let secp = Secp256k1::new(); @@ -742,7 +744,7 @@ impl KeyPair { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair}; /// /// let secp = Secp256k1::new(); @@ -788,7 +790,7 @@ impl KeyPair { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{Secp256k1, KeyPair}; /// use secp256k1::rand::{RngCore, thread_rng}; /// @@ -912,7 +914,7 @@ impl<'de> ::serde::Deserialize<'de> for KeyPair { /// Basic usage: /// /// ``` -/// # #[cfg(feature="rand")] { +/// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, KeyPair, XOnlyPublicKey}; /// /// let secp = Secp256k1::new(); @@ -1040,7 +1042,7 @@ impl XOnlyPublicKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{Secp256k1, KeyPair}; /// use secp256k1::rand::{RngCore, thread_rng}; /// @@ -1105,7 +1107,7 @@ impl XOnlyPublicKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{Secp256k1, KeyPair}; /// use secp256k1::rand::{thread_rng, RngCore}; /// @@ -1347,16 +1349,20 @@ pub mod serde_keypair { } #[cfg(test)] +#[allow(unused_imports)] mod test { use super::*; - use std::iter; - use std::str::FromStr; + #[cfg(any(feature = "alloc", feature = "std"))] + use core::iter; + use core::str::FromStr; + #[cfg(any(feature = "alloc", feature = "std"))] use rand::{Error, ErrorKind, RngCore, thread_rng}; + #[cfg(any(feature = "alloc", feature = "std"))] use rand_core::impls; - use {to_hex, constants}; + use constants; use Error::{InvalidPublicKey, InvalidSecretKey}; #[cfg(target_arch = "wasm32")] @@ -1392,6 +1398,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn keypair_slice_round_trip() { let s = Secp256k1::new(); @@ -1402,6 +1409,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn invalid_secret_key() { // Zero assert_eq!(SecretKey::from_slice(&[0; 32]), Err(InvalidSecretKey)); @@ -1428,6 +1436,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_out_of_range() { struct BadRng(u8); @@ -1520,7 +1529,10 @@ mod test { } #[test] + #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] fn test_debug_output() { + use to_hex; + struct DumbRng(u32); impl RngCore for DumbRng { fn next_u32(&mut self) -> u32 { @@ -1551,6 +1563,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_display_output() { static SK_BYTES: [u8; 32] = [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, @@ -1613,6 +1626,7 @@ mod test { // In fuzzing mode the Y coordinate is expected to match the X, so this // test uses invalid public keys. #[cfg(not(fuzzing))] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_pubkey_serialize() { struct DumbRng(u32); impl RngCore for DumbRng { @@ -1641,6 +1655,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_addition() { let s = Secp256k1::new(); @@ -1659,6 +1674,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_multiplication() { let s = Secp256k1::new(); @@ -1677,6 +1693,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_negation() { let s = Secp256k1::new(); @@ -1698,6 +1715,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn pubkey_hash() { use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -1770,6 +1788,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn create_pubkey_combine() { let s = Secp256k1::new(); @@ -1809,8 +1828,8 @@ mod test { assert!(pk1 <= pk3); } - #[cfg(feature = "serde")] #[test] + #[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))] fn test_serde() { use serde_test::{Configure, Token, assert_tokens}; static SK_BYTES: [u8; 32] = [ @@ -1862,6 +1881,7 @@ mod test { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_tweak_add_assign_then_tweak_add_check() { let s = Secp256k1::new(); diff --git a/src/lib.rs b/src/lib.rs index 0e742cd..5195bf6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,7 @@ //! trigger any assertion failures in the upstream library. //! //! ```rust -//! # #[cfg(all(feature="rand", feature="bitcoin_hashes"))] { +//! # #[cfg(all(feature="rand", feature="bitcoin_hashes", any(feature = "alloc", feature = "std")))] { //! use secp256k1::rand::rngs::OsRng; //! use secp256k1::{Secp256k1, Message}; //! use secp256k1::hashes::sha256; @@ -58,6 +58,7 @@ //! Alternately, keys and messages can be parsed from slices, like //! //! ```rust +//! # #[cfg(any(feature = "alloc", features = "std"))] { //! use secp256k1::{Secp256k1, Message, SecretKey, PublicKey}; //! //! let secp = Secp256k1::new(); @@ -69,11 +70,13 @@ //! //! let sig = secp.sign_ecdsa(&message, &secret_key); //! assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok()); +//! # } //! ``` //! //! Users who only want to verify signatures can use a cheaper context, like so: //! //! ```rust +//! # #[cfg(any(feature = "alloc", feature = "std"))] { //! use secp256k1::{Secp256k1, Message, ecdsa, PublicKey}; //! //! let secp = Secp256k1::verification_only(); @@ -106,6 +109,7 @@ //! //! # #[cfg(not(fuzzing))] //! assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok()); +//! # } //! ``` //! //! Observe that the same code using, say [`signing_only`](struct.Secp256k1.html#method.signing_only) @@ -506,8 +510,7 @@ fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> { mod tests { use super::*; use rand::{RngCore, thread_rng}; - use std::str::FromStr; - use std::marker::PhantomData; + use core::str::FromStr; use ffi::types::AlignedType; #[cfg(target_arch = "wasm32")] @@ -523,6 +526,7 @@ mod tests { #[test] + #[cfg(feature = "std")] fn test_manual_create_destroy() { let ctx_full = unsafe { ffi::secp256k1_context_create(AllPreallocated::FLAGS) }; let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) }; @@ -551,6 +555,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_raw_ctx() { use std::mem::ManuallyDrop; @@ -586,6 +591,7 @@ mod tests { #[cfg(not(target_arch = "wasm32"))] #[test] #[ignore] // Panicking from C may trap (SIGILL) intentionally, so we test this manually. + #[cfg(any(feature = "alloc", feature = "std"))] fn test_panic_raw_ctx_should_terminate_abnormally() { let ctx_vrfy = Secp256k1::verification_only(); let raw_ctx_verify_as_full = unsafe {Secp256k1::from_raw_all(ctx_vrfy.ctx)}; @@ -618,6 +624,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn capabilities() { let sign = Secp256k1::signing_only(); let vrfy = Secp256k1::verification_only(); @@ -647,6 +654,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn signature_serialize_roundtrip() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -733,6 +741,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn sign_and_verify_ecdsa() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -764,6 +773,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn sign_and_verify_extreme() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -797,6 +807,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn sign_and_verify_fail() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -858,6 +869,7 @@ mod tests { #[test] #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs + #[cfg(any(feature = "alloc", feature = "std"))] fn test_low_s() { // nb this is a transaction on testnet // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9 @@ -880,6 +892,7 @@ mod tests { #[test] #[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format + #[cfg(any(feature = "alloc", feature = "std"))] fn test_low_r() { let secp = Secp256k1::new(); let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac"); @@ -895,6 +908,7 @@ mod tests { #[test] #[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format + #[cfg(any(feature = "alloc", feature = "std"))] fn test_grind_r() { let secp = Secp256k1::new(); let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167"); @@ -909,6 +923,7 @@ mod tests { #[cfg(feature = "serde")] #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs + #[cfg(any(feature = "alloc", feature = "std"))] #[test] fn test_serde() { use serde_test::{Configure, Token, assert_tokens}; @@ -992,6 +1007,7 @@ mod benches { use super::{Secp256k1, Message}; #[bench] + #[cfg(any(feature = "alloc", feature = "std"))] pub fn generate(bh: &mut Bencher) { struct CounterRng(u64); impl RngCore for CounterRng { @@ -1027,6 +1043,7 @@ mod benches { } #[bench] + #[cfg(any(feature = "alloc", feature = "std"))] pub fn bench_sign_ecdsa(bh: &mut Bencher) { let s = Secp256k1::new(); let mut msg = [0u8; 32]; @@ -1041,6 +1058,7 @@ mod benches { } #[bench] + #[cfg(any(feature = "alloc", feature = "std"))] pub fn bench_verify_ecdsa(bh: &mut Bencher) { let s = Secp256k1::new(); let mut msg = [0u8; 32]; diff --git a/src/schnorr.rs b/src/schnorr.rs index e713913..14ac36f 100644 --- a/src/schnorr.rs +++ b/src/schnorr.rs @@ -267,19 +267,26 @@ impl Secp256k1 { } #[cfg(test)] +#[allow(unused_imports)] mod tests { - use super::super::Error::InvalidPublicKey; - use super::super::{constants, from_hex, All, Message, Secp256k1}; - use super::{KeyPair, XOnlyPublicKey, Signature}; - use rand::{rngs::ThreadRng, thread_rng, Error, ErrorKind, RngCore}; - use rand_core::impls; use std::iter; use std::str::FromStr; + use rand::rngs::ThreadRng; + use rand::{Error, ErrorKind, RngCore, thread_rng}; + use rand_core::impls; + + use {constants, Error::InvalidPublicKey, from_hex, Message, Secp256k1, SecretKey}; + + #[cfg(any(feature = "std", feature = "alloc"))] + use All; + #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::wasm_bindgen_test as test; - use SecretKey; + use super::*; + + #[cfg(any(feature = "alloc", feature = "std"))] macro_rules! hex_32 { ($hex:expr) => {{ let mut result = [0u8; 32]; @@ -289,6 +296,7 @@ mod tests { } #[test] + #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] fn test_schnorrsig_sign_with_aux_rand_verify() { test_schnorrsig_sign_helper(|secp, msg, seckey, rng| { let mut aux_rand = [0u8; 32]; @@ -298,6 +306,7 @@ mod tests { } #[test] + #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] fn test_schnorrsig_sign_with_rng_verify() { test_schnorrsig_sign_helper(|secp, msg, seckey, mut rng| { secp.sign_schnorr_with_rng(msg, seckey, &mut rng) @@ -305,6 +314,7 @@ mod tests { } #[test] + #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] fn test_schnorrsig_sign_verify() { test_schnorrsig_sign_helper(|secp, msg, seckey, _| { secp.sign_schnorr(msg, seckey) @@ -312,12 +322,14 @@ mod tests { } #[test] + #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] fn test_schnorrsig_sign_no_aux_rand_verify() { test_schnorrsig_sign_helper(|secp, msg, seckey, _| { secp.sign_schnorr_no_aux_rand(msg, seckey) }) } + #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] fn test_schnorrsig_sign_helper( sign: fn(&Secp256k1, &Message, &KeyPair, &mut ThreadRng) -> Signature, ) { @@ -340,6 +352,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs fn test_schnorrsig_sign() { let secp = Secp256k1::new(); @@ -363,6 +376,7 @@ mod tests { #[test] #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs + #[cfg(any(feature = "alloc", feature = "std"))] fn test_schnorrsig_verify() { let secp = Secp256k1::new(); @@ -389,6 +403,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_pubkey_serialize_roundtrip() { let secp = Secp256k1::new(); let kp = KeyPair::new(&secp, &mut thread_rng()); @@ -400,6 +415,7 @@ mod tests { } #[test] + #[cfg(any(feature = "alloc", feature = "std"))] fn test_xonly_key_extraction() { let secp = Secp256k1::new(); let sk_str = "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF"; @@ -440,6 +456,7 @@ mod tests { } #[test] + #[cfg(feature = "std")] fn test_pubkey_display_output() { let secp = Secp256k1::new(); static SK_BYTES: [u8; 32] = [ @@ -496,6 +513,7 @@ mod tests { // In fuzzing mode secret->public key derivation is different, so // this test will never correctly derive the static pubkey. #[cfg(not(fuzzing))] + #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] fn test_pubkey_serialize() { struct DumbRng(u32); impl RngCore for DumbRng { @@ -527,9 +545,9 @@ mod tests { ); } - #[cfg(feature = "serde")] #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[test] + #[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))] fn test_serde() { use serde_test::{assert_tokens, Configure, Token}; From ae3e06f95b7a7394c450bc8103738df9d79773f6 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 1 Feb 2022 12:49:07 +1100 Subject: [PATCH 5/7] Fix lint warnings in test code Various combinations of features trigger lint warnings for unused code, all warnings are caused by incorrect feature gating. Correct feature gating to remove Clippy warnings during testing. --- src/key.rs | 11 ++++++++--- src/schnorr.rs | 28 +++++++++++++++------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/key.rs b/src/key.rs index 9ca23d2..97ddc21 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1572,6 +1572,7 @@ mod test { 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, ]; + #[cfg(not(fuzzing))] let s = Secp256k1::signing_only(); let sk = SecretKey::from_slice(&SK_BYTES).expect("sk"); @@ -1739,7 +1740,8 @@ mod test { assert_eq!(set.len(), COUNT); } - #[cfg_attr(not(fuzzing), test)] + #[test] + #[cfg(not(fuzzing))] fn pubkey_combine() { let compressed1 = PublicKey::from_slice( &hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"), @@ -1759,7 +1761,8 @@ mod test { assert_eq!(sum1.unwrap(), exp_sum); } - #[cfg_attr(not(fuzzing), test)] + #[test] + #[cfg(not(fuzzing))] fn pubkey_combine_keys() { let compressed1 = PublicKey::from_slice( &hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"), @@ -1782,7 +1785,8 @@ mod test { assert_eq!(sum1.unwrap(), exp_sum); } - #[cfg_attr(not(fuzzing), test)] + #[test] + #[cfg(not(fuzzing))] fn pubkey_combine_keys_empty_slice() { assert!(PublicKey::combine_keys(&[]).is_err()); } @@ -1852,6 +1856,7 @@ mod test { 0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166\ "; + #[cfg(not(fuzzing))] let s = Secp256k1::new(); let sk = SecretKey::from_slice(&SK_BYTES).unwrap(); diff --git a/src/schnorr.rs b/src/schnorr.rs index 14ac36f..ea536f5 100644 --- a/src/schnorr.rs +++ b/src/schnorr.rs @@ -286,7 +286,7 @@ mod tests { use super::*; - #[cfg(any(feature = "alloc", feature = "std"))] + #[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))] macro_rules! hex_32 { ($hex:expr) => {{ let mut result = [0u8; 32]; @@ -458,19 +458,21 @@ mod tests { #[test] #[cfg(feature = "std")] fn test_pubkey_display_output() { - let secp = Secp256k1::new(); - static SK_BYTES: [u8; 32] = [ - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, - ]; - - let kp = KeyPair::from_seckey_slice(&secp, &SK_BYTES).expect("sk"); - - // In fuzzing mode secret->public key derivation is different, so - // hard-code the epected result. #[cfg(not(fuzzing))] - let pk = kp.public_key(); + let pk = { + let secp = Secp256k1::new(); + static SK_BYTES: [u8; 32] = [ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, + ]; + + let kp = KeyPair::from_seckey_slice(&secp, &SK_BYTES).expect("sk"); + + // In fuzzing mode secret->public key derivation is different, so + // hard-code the epected result. + kp.public_key() + }; #[cfg(fuzzing)] let pk = XOnlyPublicKey::from_slice(&[0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66]).expect("pk"); From f3688ecf5690a3a1b3738745a1ca244f3778fc60 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 1 Feb 2022 14:00:10 +1100 Subject: [PATCH 6/7] Use rand-std in key rustdoc examples Seems there is a bug in cargo, the tests in `key.rs` run successfully but AFAICT they should fail. Here is an example, running `cargo test --features=rand` should make this test fail but it doesn't? ``` /// Secret 256-bit key used as `x` in an ECDSA signature. /// /// # Examples /// /// Basic usage: /// /// ``` /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey}; /// /// let secp = Secp256k1::new(); /// let secret_key = SecretKey::new(&mut rand::thread_rng()); /// # } /// ``` Anywho, use the correct feature gate: `rand-std`. --- src/key.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/key.rs b/src/key.rs index 97ddc21..2ce01ab 100644 --- a/src/key.rs +++ b/src/key.rs @@ -35,7 +35,7 @@ use ffi::{self, CPtr}; /// Basic usage: /// /// ``` -/// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { +/// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey}; /// /// let secp = Secp256k1::new(); @@ -129,7 +129,7 @@ impl SecretKey { /// # Examples /// /// ``` - /// # #[cfg(feature="rand")] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, SecretKey}; /// let secret_key = SecretKey::new(&mut rand::thread_rng()); /// # } @@ -185,7 +185,7 @@ impl SecretKey { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair}; /// /// let secp = Secp256k1::new(); @@ -329,7 +329,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey, PublicKey}; /// /// let secp = Secp256k1::new(); @@ -377,7 +377,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, PublicKey, KeyPair}; /// /// let secp = Secp256k1::new(); @@ -508,7 +508,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1}; /// /// let secp = Secp256k1::new(); @@ -534,7 +534,7 @@ impl PublicKey { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, PublicKey}; /// /// let secp = Secp256k1::new(); @@ -650,7 +650,7 @@ impl Ord for PublicKey { /// Basic usage: /// /// ``` -/// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { +/// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, KeyPair, Secp256k1}; /// /// let secp = Secp256k1::new(); @@ -744,7 +744,7 @@ impl KeyPair { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair}; /// /// let secp = Secp256k1::new(); @@ -790,7 +790,7 @@ impl KeyPair { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{Secp256k1, KeyPair}; /// use secp256k1::rand::{RngCore, thread_rng}; /// @@ -914,7 +914,7 @@ impl<'de> ::serde::Deserialize<'de> for KeyPair { /// Basic usage: /// /// ``` -/// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { +/// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{rand, Secp256k1, KeyPair, XOnlyPublicKey}; /// /// let secp = Secp256k1::new(); @@ -1042,7 +1042,7 @@ impl XOnlyPublicKey { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{Secp256k1, KeyPair}; /// use secp256k1::rand::{RngCore, thread_rng}; /// @@ -1107,7 +1107,7 @@ impl XOnlyPublicKey { /// # Examples /// /// ``` - /// # #[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))] { + /// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] { /// use secp256k1::{Secp256k1, KeyPair}; /// use secp256k1::rand::{thread_rng, RngCore}; /// From c30026d08b5489386af1048936d457f04785a34a Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Thu, 3 Feb 2022 08:36:36 +1100 Subject: [PATCH 7/7] Fix typo 'epected' -> 'expected' Fix minor spelling mistake in code comments. --- src/key.rs | 4 ++-- src/schnorr.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/key.rs b/src/key.rs index 2ce01ab..bfebe63 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1577,7 +1577,7 @@ mod test { let sk = SecretKey::from_slice(&SK_BYTES).expect("sk"); // In fuzzing mode secret->public key derivation is different, so - // hard-code the epected result. + // hard-code the expected result. #[cfg(not(fuzzing))] let pk = PublicKey::from_secret_key(&s, &sk); #[cfg(fuzzing)] @@ -1861,7 +1861,7 @@ mod test { let sk = SecretKey::from_slice(&SK_BYTES).unwrap(); // In fuzzing mode secret->public key derivation is different, so - // hard-code the epected result. + // hard-code the expected result. #[cfg(not(fuzzing))] let pk = PublicKey::from_secret_key(&s, &sk); #[cfg(fuzzing)] diff --git a/src/schnorr.rs b/src/schnorr.rs index ea536f5..c709573 100644 --- a/src/schnorr.rs +++ b/src/schnorr.rs @@ -470,7 +470,7 @@ mod tests { let kp = KeyPair::from_seckey_slice(&secp, &SK_BYTES).expect("sk"); // In fuzzing mode secret->public key derivation is different, so - // hard-code the epected result. + // hard-code the expected result. kp.public_key() }; #[cfg(fuzzing)]