Merge rust-bitcoin/rust-secp256k1#520: Fix feature gating
9c748550b4
Fix feature gating (Tobin C. Harding) Pull request description: Currently we have a few problems with our feature gating, attempt to audit all feature gating and fix it by doing: 1. Do not enable features on optional dependencies (`rand` and `bitcoin-hashes`) in dev-dependencies, doing so hides broken feature gating in unit tests. 2. Do not use unnecessary feature combinations when one feature enables another e.g. `any(feature = "std", feature = "alloc")`. 3. Enable "std" from "rand-std" and "bitcoin-std" (and fix features gating as for point 2). 4. Clean up code around `rand::thread_rng`, this is part of this patch because `thread_rng` requires the "rand-std" feature. 5. Clean up CI test script to test each feature individually now that "rand-std" and "bitcoin-hashes-std" enable "std". ACKs for top commit: apoelstra: ACK9c748550b4
Kixunil: ACK9c748550b4
Tree-SHA512: 3f8e464eeab1fe279249b5097082774c3de076ec9537162f367013098bde45957b12067a7434389e520bfacd3b415274f897917bf000f332d52cf960b1d4aecf
This commit is contained in:
commit
29c0549e51
12
Cargo.toml
12
Cargo.toml
|
@ -23,8 +23,8 @@ std = ["alloc", "secp256k1-sys/std"]
|
||||||
# allow use of Secp256k1::new and related API that requires an allocator
|
# allow use of Secp256k1::new and related API that requires an allocator
|
||||||
alloc = ["secp256k1-sys/alloc"]
|
alloc = ["secp256k1-sys/alloc"]
|
||||||
bitcoin-hashes = ["bitcoin_hashes"] # Feature alias because of the underscore.
|
bitcoin-hashes = ["bitcoin_hashes"] # Feature alias because of the underscore.
|
||||||
bitcoin-hashes-std = ["bitcoin-hashes", "bitcoin_hashes/std"]
|
bitcoin-hashes-std = ["std", "bitcoin_hashes/std"]
|
||||||
rand-std = ["rand/std", "rand/std_rng"]
|
rand-std = ["std", "rand/std", "rand/std_rng"]
|
||||||
recovery = ["secp256k1-sys/recovery"]
|
recovery = ["secp256k1-sys/recovery"]
|
||||||
lowmemory = ["secp256k1-sys/lowmemory"]
|
lowmemory = ["secp256k1-sys/lowmemory"]
|
||||||
global-context = ["std"]
|
global-context = ["std"]
|
||||||
|
@ -46,10 +46,8 @@ bitcoin_hashes = { version = "0.11", default-features = false, optional = true }
|
||||||
rand = { version = "0.8", default-features = false, optional = true }
|
rand = { version = "0.8", default-features = false, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.8"
|
|
||||||
rand_core = "0.6"
|
rand_core = "0.6"
|
||||||
serde_test = "1.0"
|
serde_test = "1.0"
|
||||||
bitcoin_hashes = "0.11"
|
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
|
|
||||||
# cbor does not build on WASM, we use it in a single trivial test (an example of when
|
# cbor does not build on WASM, we use it in a single trivial test (an example of when
|
||||||
|
@ -64,15 +62,15 @@ getrandom = { version = "0.2", features = ["js"] }
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "sign_verify_recovery"
|
name = "sign_verify_recovery"
|
||||||
required-features = ["std", "recovery"]
|
required-features = ["recovery", "bitcoin-hashes-std"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "sign_verify"
|
name = "sign_verify"
|
||||||
required-features = ["std"]
|
required-features = ["bitcoin-hashes-std"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "generate_keys"
|
name = "generate_keys"
|
||||||
required-features = ["std", "rand-std"]
|
required-features = ["rand-std"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["secp256k1-sys"]
|
members = ["secp256k1-sys"]
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
|
|
||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
FEATURES="bitcoin-hashes global-context lowmemory rand recovery serde std alloc"
|
FEATURES="bitcoin-hashes global-context lowmemory rand recovery serde std alloc bitcoin-hashes-std rand-std"
|
||||||
# These features are typically enabled along with the 'std' feature, so we test
|
|
||||||
# them together with 'std'.
|
|
||||||
STD_FEATURES="rand-std bitcoin-hashes-std"
|
|
||||||
|
|
||||||
cargo --version
|
cargo --version
|
||||||
rustc --version
|
rustc --version
|
||||||
|
@ -49,7 +46,6 @@ if [ "$DO_FEATURE_MATRIX" = true ]; then
|
||||||
RUSTFLAGS='--cfg=fuzzing' RUSTDOCFLAGS='--cfg=fuzzing' cargo test --all
|
RUSTFLAGS='--cfg=fuzzing' RUSTDOCFLAGS='--cfg=fuzzing' cargo test --all
|
||||||
RUSTFLAGS='--cfg=fuzzing' RUSTDOCFLAGS='--cfg=fuzzing' cargo test --all --features="$FEATURES"
|
RUSTFLAGS='--cfg=fuzzing' RUSTDOCFLAGS='--cfg=fuzzing' cargo test --all --features="$FEATURES"
|
||||||
cargo test --all --features="rand serde"
|
cargo test --all --features="rand serde"
|
||||||
cargo test --features="$STD_FEATURES"
|
|
||||||
|
|
||||||
if [ "$NIGHTLY" = true ]; then
|
if [ "$NIGHTLY" = true ]; then
|
||||||
cargo test --all --all-features
|
cargo test --all --all-features
|
||||||
|
@ -57,9 +53,9 @@ if [ "$DO_FEATURE_MATRIX" = true ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
cargo run --example sign_verify --features=std
|
cargo run --example sign_verify --features=bitcoin-hashes-std
|
||||||
cargo run --example sign_verify_recovery --features=std,recovery
|
cargo run --example sign_verify_recovery --features=recovery,bitcoin-hashes-std
|
||||||
cargo run --example generate_keys --features=std,rand-std
|
cargo run --example generate_keys --features=rand-std
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build the docs if told to (this only works with the nightly toolchain)
|
# Build the docs if told to (this only works with the nightly toolchain)
|
||||||
|
@ -96,7 +92,7 @@ fi
|
||||||
# Bench if told to, only works with non-stable toolchain (nightly, beta).
|
# Bench if told to, only works with non-stable toolchain (nightly, beta).
|
||||||
if [ "$DO_BENCH" = true ]
|
if [ "$DO_BENCH" = true ]
|
||||||
then
|
then
|
||||||
RUSTFLAGS='--cfg=bench' cargo bench --features=recovery
|
RUSTFLAGS='--cfg=bench' cargo bench --features=recovery,rand-std
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
extern crate secp256k1;
|
extern crate secp256k1;
|
||||||
|
|
||||||
use secp256k1::rand::thread_rng;
|
|
||||||
use secp256k1::{PublicKey, Secp256k1, SecretKey};
|
use secp256k1::{PublicKey, Secp256k1, SecretKey};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let mut rng = thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
// First option:
|
// First option:
|
||||||
let (seckey, pubkey) = secp.generate_keypair(&mut rng);
|
let (seckey, pubkey) = secp.generate_keypair(&mut rng);
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,7 @@ pub mod global {
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "global-context", feature = "rand-std"))] {
|
/// # #[cfg(all(feature = "global-context", feature = "rand-std"))] {
|
||||||
/// use secp256k1::{PublicKey, SECP256K1};
|
/// use secp256k1::{PublicKey, SECP256K1};
|
||||||
/// use secp256k1::rand::thread_rng;
|
/// let _ = SECP256K1.generate_keypair(&mut rand::thread_rng());
|
||||||
/// let _ = SECP256K1.generate_keypair(&mut thread_rng());
|
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub static SECP256K1: &GlobalContext = &GlobalContext { __private: () };
|
pub static SECP256K1: &GlobalContext = &GlobalContext { __private: () };
|
||||||
|
@ -106,7 +105,7 @@ mod private {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
|
||||||
mod alloc_only {
|
mod alloc_only {
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
@ -176,7 +175,7 @@ mod alloc_only {
|
||||||
/// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`.
|
/// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`.
|
||||||
/// If `rand-std` feature is not enabled please consider randomizing the context as follows:
|
/// If `rand-std` feature is not enabled please consider randomizing the context as follows:
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// # use secp256k1::Secp256k1;
|
/// # use secp256k1::Secp256k1;
|
||||||
/// # use secp256k1::rand::{thread_rng, RngCore};
|
/// # use secp256k1::rand::{thread_rng, RngCore};
|
||||||
/// let mut ctx = Secp256k1::new();
|
/// let mut ctx = Secp256k1::new();
|
||||||
|
|
37
src/ecdh.rs
37
src/ecdh.rs
|
@ -32,13 +32,12 @@ const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// # use secp256k1::Secp256k1;
|
/// # use secp256k1::{rand, Secp256k1};
|
||||||
/// # use secp256k1::ecdh::SharedSecret;
|
/// # use secp256k1::ecdh::SharedSecret;
|
||||||
/// # use secp256k1::rand::thread_rng;
|
|
||||||
/// let s = Secp256k1::new();
|
/// let s = Secp256k1::new();
|
||||||
/// let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
|
/// let (sk1, pk1) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
/// let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
|
/// let (sk2, pk2) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
/// let sec1 = SharedSecret::new(&pk2, &sk1);
|
/// let sec1 = SharedSecret::new(&pk2, &sk1);
|
||||||
/// let sec2 = SharedSecret::new(&pk1, &sk2);
|
/// let sec2 = SharedSecret::new(&pk1, &sk2);
|
||||||
/// assert_eq!(sec1, sec2);
|
/// assert_eq!(sec1, sec2);
|
||||||
|
@ -122,14 +121,13 @@ impl AsRef<[u8]> for SharedSecret {
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "bitcoin-hashes-std", feature = "rand-std", feature = "std"))] {
|
/// # #[cfg(all(feature = "bitcoin-hashes-std", feature = "rand-std"))] {
|
||||||
/// # use secp256k1::{ecdh, Secp256k1, PublicKey, SecretKey};
|
/// # use secp256k1::{ecdh, rand, Secp256k1, PublicKey, SecretKey};
|
||||||
/// # use secp256k1::hashes::{Hash, sha512};
|
/// # use secp256k1::hashes::{Hash, sha512};
|
||||||
/// # use secp256k1::rand::thread_rng;
|
|
||||||
///
|
///
|
||||||
/// let s = Secp256k1::new();
|
/// let s = Secp256k1::new();
|
||||||
/// let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
|
/// let (sk1, pk1) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
/// let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
|
/// let (sk2, pk2) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
///
|
///
|
||||||
/// let point1 = ecdh::shared_secret_point(&pk2, &sk1);
|
/// let point1 = ecdh::shared_secret_point(&pk2, &sk1);
|
||||||
/// let secret1 = sha512::Hash::hash(&point1);
|
/// let secret1 = sha512::Hash::hash(&point1);
|
||||||
|
@ -201,7 +199,6 @@ impl<'de> ::serde::Deserialize<'de> for SharedSecret {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use rand::thread_rng;
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
|
@ -209,11 +206,11 @@ mod tests {
|
||||||
use crate::Secp256k1;
|
use crate::Secp256k1;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn ecdh() {
|
fn ecdh() {
|
||||||
let s = Secp256k1::signing_only();
|
let s = Secp256k1::signing_only();
|
||||||
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
|
let (sk1, pk1) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
|
let (sk2, pk2) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sec1 = SharedSecret::new(&pk2, &sk1);
|
let sec1 = SharedSecret::new(&pk2, &sk1);
|
||||||
let sec2 = SharedSecret::new(&pk1, &sk2);
|
let sec2 = SharedSecret::new(&pk1, &sk2);
|
||||||
|
@ -241,15 +238,15 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(not(fuzzing))]
|
#[cfg(not(fuzzing))]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std", feature = "bitcoin-hashes-std"))]
|
#[cfg(all(feature = "bitcoin-hashes-std", feature = "rand-std"))]
|
||||||
fn bitcoin_hashes_and_sys_generate_same_secret() {
|
fn bitcoin_hashes_and_sys_generate_same_secret() {
|
||||||
use bitcoin_hashes::{sha256, Hash, HashEngine};
|
use bitcoin_hashes::{sha256, Hash, HashEngine};
|
||||||
|
|
||||||
use crate::ecdh::shared_secret_point;
|
use crate::ecdh::shared_secret_point;
|
||||||
|
|
||||||
let s = Secp256k1::signing_only();
|
let s = Secp256k1::signing_only();
|
||||||
let (sk1, _) = s.generate_keypair(&mut thread_rng());
|
let (sk1, _) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let (_, pk2) = s.generate_keypair(&mut thread_rng());
|
let (_, pk2) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let secret_sys = SharedSecret::new(&pk2, &sk1);
|
let secret_sys = SharedSecret::new(&pk2, &sk1);
|
||||||
|
|
||||||
|
@ -266,7 +263,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "serde", feature = "alloc"))]
|
||||||
fn serde() {
|
fn serde() {
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -291,8 +288,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(bench)]
|
#[cfg(bench)]
|
||||||
|
#[cfg(feature = "rand-std")] // Currently only a single bench that requires "rand-std".
|
||||||
mod benches {
|
mod benches {
|
||||||
use rand::thread_rng;
|
|
||||||
use test::{black_box, Bencher};
|
use test::{black_box, Bencher};
|
||||||
|
|
||||||
use super::SharedSecret;
|
use super::SharedSecret;
|
||||||
|
@ -301,7 +298,7 @@ mod benches {
|
||||||
#[bench]
|
#[bench]
|
||||||
pub fn bench_ecdh(bh: &mut Bencher) {
|
pub fn bench_ecdh(bh: &mut Bencher) {
|
||||||
let s = Secp256k1::signing_only();
|
let s = Secp256k1::signing_only();
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
let res = SharedSecret::new(&pk, &sk);
|
let res = SharedSecret::new(&pk, &sk);
|
||||||
|
|
|
@ -364,12 +364,11 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
/// verify-capable context.
|
/// verify-capable context.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// # use secp256k1::rand::thread_rng;
|
/// # use secp256k1::{rand, Secp256k1, Message, Error};
|
||||||
/// # use secp256k1::{Secp256k1, Message, Error};
|
|
||||||
/// #
|
/// #
|
||||||
/// # let secp = Secp256k1::new();
|
/// # let secp = Secp256k1::new();
|
||||||
/// # let (secret_key, public_key) = secp.generate_keypair(&mut thread_rng());
|
/// # let (secret_key, public_key) = secp.generate_keypair(&mut rand::thread_rng());
|
||||||
/// #
|
/// #
|
||||||
/// let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
|
/// let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
|
||||||
/// let sig = secp.sign_ecdsa(&message, &secret_key);
|
/// let sig = secp.sign_ecdsa(&message, &secret_key);
|
||||||
|
|
|
@ -220,7 +220,6 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
|
@ -229,18 +228,17 @@ mod tests {
|
||||||
use crate::{Error, Message, Secp256k1, SecretKey};
|
use crate::{Error, Message, Secp256k1, SecretKey};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn capabilities() {
|
fn capabilities() {
|
||||||
let sign = Secp256k1::signing_only();
|
let sign = Secp256k1::signing_only();
|
||||||
let vrfy = Secp256k1::verification_only();
|
let vrfy = Secp256k1::verification_only();
|
||||||
let full = Secp256k1::new();
|
let full = Secp256k1::new();
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
// Try key generation
|
// Try key generation
|
||||||
let (sk, pk) = full.generate_keypair(&mut thread_rng());
|
let (sk, pk) = full.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
// Try signing
|
// Try signing
|
||||||
assert_eq!(sign.sign_ecdsa_recoverable(&msg, &sk), full.sign_ecdsa_recoverable(&msg, &sk));
|
assert_eq!(sign.sign_ecdsa_recoverable(&msg, &sk), full.sign_ecdsa_recoverable(&msg, &sk));
|
||||||
|
@ -262,11 +260,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
#[cfg(all(feature="std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn sign() {
|
fn sign() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sk = SecretKey::from_slice(&ONE).unwrap();
|
let sk = SecretKey::from_slice(&ONE).unwrap();
|
||||||
let msg = Message::from_slice(&ONE).unwrap();
|
let msg = Message::from_slice(&ONE).unwrap();
|
||||||
|
@ -287,11 +285,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
#[cfg(all(feature="std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn sign_with_noncedata() {
|
fn sign_with_noncedata() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sk = SecretKey::from_slice(&ONE).unwrap();
|
let sk = SecretKey::from_slice(&ONE).unwrap();
|
||||||
let msg = Message::from_slice(&ONE).unwrap();
|
let msg = Message::from_slice(&ONE).unwrap();
|
||||||
|
@ -312,22 +310,20 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn sign_and_verify_fail() {
|
fn sign_and_verify_fail() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sigr = s.sign_ecdsa_recoverable(&msg, &sk);
|
let sigr = s.sign_ecdsa_recoverable(&msg, &sk);
|
||||||
let sig = sigr.to_standard();
|
let sig = sigr.to_standard();
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
assert_eq!(s.verify_ecdsa(&msg, &sig, &pk), Err(Error::IncorrectSignature));
|
assert_eq!(s.verify_ecdsa(&msg, &sig, &pk), Err(Error::IncorrectSignature));
|
||||||
|
|
||||||
|
@ -336,16 +332,15 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn sign_with_recovery() {
|
fn sign_with_recovery() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sig = s.sign_ecdsa_recoverable(&msg, &sk);
|
let sig = s.sign_ecdsa_recoverable(&msg, &sk);
|
||||||
|
|
||||||
|
@ -353,18 +348,17 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn sign_with_recovery_and_noncedata() {
|
fn sign_with_recovery_and_noncedata() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
let noncedata = [42u8; 32];
|
let noncedata = [42u8; 32];
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sig = s.sign_ecdsa_recoverable_with_noncedata(&msg, &sk, &noncedata);
|
let sig = s.sign_ecdsa_recoverable_with_noncedata(&msg, &sk, &noncedata);
|
||||||
|
|
||||||
|
@ -372,10 +366,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn bad_recovery() {
|
fn bad_recovery() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let msg = Message::from_slice(&[0x55; 32]).unwrap();
|
let msg = Message::from_slice(&[0x55; 32]).unwrap();
|
||||||
|
|
||||||
|
@ -438,8 +432,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(bench)]
|
#[cfg(bench)]
|
||||||
|
#[cfg(feature = "rand-std")] // Currently only a single bench that requires "rand-std".
|
||||||
mod benches {
|
mod benches {
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
use test::{black_box, Bencher};
|
use test::{black_box, Bencher};
|
||||||
|
|
||||||
use super::{Message, Secp256k1};
|
use super::{Message, Secp256k1};
|
||||||
|
@ -447,10 +441,9 @@ mod benches {
|
||||||
#[bench]
|
#[bench]
|
||||||
pub fn bench_recover(bh: &mut Bencher) {
|
pub fn bench_recover(bh: &mut Bencher) {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
let (sk, _) = s.generate_keypair(&mut thread_rng());
|
let (sk, _) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let sig = s.sign_ecdsa_recoverable(&msg, &sk);
|
let sig = s.sign_ecdsa_recoverable(&msg, &sk);
|
||||||
|
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
|
|
138
src/key.rs
138
src/key.rs
|
@ -47,7 +47,7 @@ use crate::{hashes, ThirtyTwoByteHash};
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1, SecretKey};
|
/// use secp256k1::{rand, Secp256k1, SecretKey};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -84,7 +84,7 @@ impl str::FromStr for SecretKey {
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(any(feature = "alloc", feature = "std"))] {
|
/// # #[cfg(feature = "alloc")] {
|
||||||
/// use secp256k1::{SecretKey, Secp256k1, PublicKey};
|
/// use secp256k1::{SecretKey, Secp256k1, PublicKey};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -126,13 +126,6 @@ impl str::FromStr for PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "rand"))]
|
|
||||||
fn random_32_bytes<R: rand::Rng + ?Sized>(rng: &mut R) -> [u8; 32] {
|
|
||||||
let mut ret = [0u8; 32];
|
|
||||||
rng.fill_bytes(&mut ret);
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SecretKey {
|
impl SecretKey {
|
||||||
/// Generates a new random secret key.
|
/// Generates a new random secret key.
|
||||||
///
|
///
|
||||||
|
@ -145,17 +138,17 @@ impl SecretKey {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub fn new<R: rand::Rng + ?Sized>(rng: &mut R) -> SecretKey {
|
pub fn new<R: rand::Rng + ?Sized>(rng: &mut R) -> SecretKey {
|
||||||
let mut data = random_32_bytes(rng);
|
let mut data = crate::random_32_bytes(rng);
|
||||||
unsafe {
|
unsafe {
|
||||||
while ffi::secp256k1_ec_seckey_verify(
|
while ffi::secp256k1_ec_seckey_verify(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
data.as_c_ptr(),
|
data.as_c_ptr(),
|
||||||
) == 0
|
) == 0
|
||||||
{
|
{
|
||||||
data = random_32_bytes(rng);
|
data = crate::random_32_bytes(rng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SecretKey(data)
|
SecretKey(data)
|
||||||
|
@ -193,7 +186,7 @@ impl SecretKey {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair};
|
/// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -394,7 +387,7 @@ impl PublicKey {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1, SecretKey, PublicKey};
|
/// use secp256k1::{rand, Secp256k1, SecretKey, PublicKey};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -450,7 +443,7 @@ impl PublicKey {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1, PublicKey, KeyPair};
|
/// use secp256k1::{rand, Secp256k1, PublicKey, KeyPair};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -579,7 +572,7 @@ impl PublicKey {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1};
|
/// use secp256k1::{rand, Secp256k1};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -605,7 +598,7 @@ impl PublicKey {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1, PublicKey};
|
/// use secp256k1::{rand, Secp256k1, PublicKey};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -769,7 +762,7 @@ impl core::hash::Hash for PublicKey {
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, KeyPair, Secp256k1};
|
/// use secp256k1::{rand, KeyPair, Secp256k1};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -866,7 +859,7 @@ impl KeyPair {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair};
|
/// use secp256k1::{rand, Secp256k1, SecretKey, KeyPair};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -874,19 +867,14 @@ impl KeyPair {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub fn new<R: rand::Rng + ?Sized, C: Signing>(secp: &Secp256k1<C>, rng: &mut R) -> KeyPair {
|
pub fn new<R: rand::Rng + ?Sized, C: Signing>(secp: &Secp256k1<C>, rng: &mut R) -> KeyPair {
|
||||||
let mut random_32_bytes = || {
|
let mut data = crate::random_32_bytes(rng);
|
||||||
let mut ret = [0u8; 32];
|
|
||||||
rng.fill_bytes(&mut ret);
|
|
||||||
ret
|
|
||||||
};
|
|
||||||
let mut data = random_32_bytes();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut keypair = ffi::KeyPair::new();
|
let mut keypair = ffi::KeyPair::new();
|
||||||
while ffi::secp256k1_keypair_create(secp.ctx, &mut keypair, data.as_c_ptr()) == 0 {
|
while ffi::secp256k1_keypair_create(secp.ctx, &mut keypair, data.as_c_ptr()) == 0 {
|
||||||
data = random_32_bytes();
|
data = crate::random_32_bytes(rng);
|
||||||
}
|
}
|
||||||
KeyPair(keypair)
|
KeyPair(keypair)
|
||||||
}
|
}
|
||||||
|
@ -918,14 +906,13 @@ impl KeyPair {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{Secp256k1, KeyPair, Scalar};
|
/// use secp256k1::{Secp256k1, KeyPair, Scalar};
|
||||||
/// use secp256k1::rand::{RngCore, thread_rng};
|
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
/// let tweak = Scalar::random();
|
/// let tweak = Scalar::random();
|
||||||
///
|
///
|
||||||
/// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
|
/// let mut key_pair = KeyPair::new(&secp, &mut rand::thread_rng());
|
||||||
/// let tweaked = key_pair.add_xonly_tweak(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
|
/// let tweaked = key_pair.add_xonly_tweak(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -999,6 +986,7 @@ impl<'a> From<&'a KeyPair> for PublicKey {
|
||||||
impl str::FromStr for KeyPair {
|
impl str::FromStr for KeyPair {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
|
#[allow(unused_variables, unreachable_code)] // When built with no default features.
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
let ctx = SECP256K1;
|
let ctx = SECP256K1;
|
||||||
|
@ -1081,7 +1069,7 @@ impl CPtr for KeyPair {
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{rand, Secp256k1, KeyPair, XOnlyPublicKey};
|
/// use secp256k1::{rand, Secp256k1, KeyPair, XOnlyPublicKey};
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
|
@ -1212,14 +1200,13 @@ impl XOnlyPublicKey {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{Secp256k1, KeyPair, Scalar, XOnlyPublicKey};
|
/// use secp256k1::{Secp256k1, KeyPair, Scalar, XOnlyPublicKey};
|
||||||
/// use secp256k1::rand::{RngCore, thread_rng};
|
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
/// let tweak = Scalar::random();
|
/// let tweak = Scalar::random();
|
||||||
///
|
///
|
||||||
/// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
|
/// let mut key_pair = KeyPair::new(&secp, &mut rand::thread_rng());
|
||||||
/// let (xonly, _parity) = key_pair.x_only_public_key();
|
/// let (xonly, _parity) = key_pair.x_only_public_key();
|
||||||
/// let tweaked = xonly.add_tweak(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
|
/// let tweaked = xonly.add_tweak(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
|
||||||
/// # }
|
/// # }
|
||||||
|
@ -1273,14 +1260,13 @@ impl XOnlyPublicKey {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(feature = "rand-std")] {
|
||||||
/// use secp256k1::{Secp256k1, KeyPair, Scalar};
|
/// use secp256k1::{Secp256k1, KeyPair, Scalar};
|
||||||
/// use secp256k1::rand::{thread_rng, RngCore};
|
|
||||||
///
|
///
|
||||||
/// let secp = Secp256k1::new();
|
/// let secp = Secp256k1::new();
|
||||||
/// let tweak = Scalar::random();
|
/// let tweak = Scalar::random();
|
||||||
///
|
///
|
||||||
/// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
|
/// let mut key_pair = KeyPair::new(&secp, &mut rand::thread_rng());
|
||||||
/// let (mut public_key, _) = key_pair.x_only_public_key();
|
/// let (mut public_key, _) = key_pair.x_only_public_key();
|
||||||
/// let original = public_key;
|
/// let original = public_key;
|
||||||
/// let (tweaked, parity) = public_key.add_tweak(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
|
/// let (tweaked, parity) = public_key.add_tweak(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
|
||||||
|
@ -1562,9 +1548,8 @@ pub mod serde_keypair {
|
||||||
mod test {
|
mod test {
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
use bitcoin_hashes::hex::ToHex;
|
#[cfg(feature = "rand")]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
use rand::{self, RngCore, rngs::mock::StepRng};
|
||||||
use rand::{rngs::mock::StepRng, thread_rng, Error, RngCore};
|
|
||||||
use serde_test::{Configure, Token};
|
use serde_test::{Configure, Token};
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
@ -1612,18 +1597,17 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn keypair_slice_round_trip() {
|
fn keypair_slice_round_trip() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
|
let (sk1, pk1) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
assert_eq!(SecretKey::from_slice(&sk1[..]), Ok(sk1));
|
assert_eq!(SecretKey::from_slice(&sk1[..]), Ok(sk1));
|
||||||
assert_eq!(PublicKey::from_slice(&pk1.serialize()[..]), Ok(pk1));
|
assert_eq!(PublicKey::from_slice(&pk1.serialize()[..]), Ok(pk1));
|
||||||
assert_eq!(PublicKey::from_slice(&pk1.serialize_uncompressed()[..]), Ok(pk1));
|
assert_eq!(PublicKey::from_slice(&pk1.serialize_uncompressed()[..]), Ok(pk1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn invalid_secret_key() {
|
fn invalid_secret_key() {
|
||||||
// Zero
|
// Zero
|
||||||
|
@ -1651,7 +1635,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(all(feature = "rand", feature = "alloc"))]
|
||||||
fn test_out_of_range() {
|
fn test_out_of_range() {
|
||||||
struct BadRng(u8);
|
struct BadRng(u8);
|
||||||
impl RngCore for BadRng {
|
impl RngCore for BadRng {
|
||||||
|
@ -1672,7 +1656,7 @@ mod test {
|
||||||
data[31] = self.0;
|
data[31] = self.0;
|
||||||
self.0 -= 1;
|
self.0 -= 1;
|
||||||
}
|
}
|
||||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
|
||||||
self.fill_bytes(dest);
|
self.fill_bytes(dest);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1738,7 +1722,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "rand", feature = "alloc"))]
|
||||||
fn test_debug_output() {
|
fn test_debug_output() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let (sk, _) = s.generate_keypair(&mut StepRng::new(1, 1));
|
let (sk, _) = s.generate_keypair(&mut StepRng::new(1, 1));
|
||||||
|
@ -1753,7 +1737,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "alloc")]
|
||||||
fn test_display_output() {
|
fn test_display_output() {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
static SK_BYTES: [u8; 32] = [
|
static SK_BYTES: [u8; 32] = [
|
||||||
|
@ -1859,7 +1843,7 @@ mod test {
|
||||||
// In fuzzing mode the Y coordinate is expected to match the X, so this
|
// In fuzzing mode the Y coordinate is expected to match the X, so this
|
||||||
// test uses invalid public keys.
|
// test uses invalid public keys.
|
||||||
#[cfg(not(fuzzing))]
|
#[cfg(not(fuzzing))]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(all(feature = "alloc", feature = "rand"))]
|
||||||
fn test_pubkey_serialize() {
|
fn test_pubkey_serialize() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let (_, pk1) = s.generate_keypair(&mut StepRng::new(1, 1));
|
let (_, pk1) = s.generate_keypair(&mut StepRng::new(1, 1));
|
||||||
|
@ -1886,7 +1870,7 @@ mod test {
|
||||||
fn tweak_add_arbitrary_data() {
|
fn tweak_add_arbitrary_data() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk); // Sanity check.
|
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk); // Sanity check.
|
||||||
|
|
||||||
// TODO: This would be better tested with a _lot_ of different tweaks.
|
// TODO: This would be better tested with a _lot_ of different tweaks.
|
||||||
|
@ -1901,11 +1885,11 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn tweak_add_zero() {
|
fn tweak_add_zero() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let tweak = Scalar::ZERO;
|
let tweak = Scalar::ZERO;
|
||||||
|
|
||||||
|
@ -1920,7 +1904,7 @@ mod test {
|
||||||
fn tweak_mul_arbitrary_data() {
|
fn tweak_mul_arbitrary_data() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk); // Sanity check.
|
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk); // Sanity check.
|
||||||
|
|
||||||
// TODO: This would be better tested with a _lot_ of different tweaks.
|
// TODO: This would be better tested with a _lot_ of different tweaks.
|
||||||
|
@ -1935,21 +1919,21 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn tweak_mul_zero() {
|
fn tweak_mul_zero() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let (sk, _) = s.generate_keypair(&mut thread_rng());
|
let (sk, _) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let tweak = Scalar::ZERO;
|
let tweak = Scalar::ZERO;
|
||||||
assert!(sk.mul_tweak(&tweak).is_err())
|
assert!(sk.mul_tweak(&tweak).is_err())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn test_negation() {
|
fn test_negation() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk); // Sanity check.
|
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk); // Sanity check.
|
||||||
|
|
||||||
|
@ -1967,7 +1951,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn pubkey_hash() {
|
fn pubkey_hash() {
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -1983,7 +1967,7 @@ mod test {
|
||||||
let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
const COUNT: usize = 1024;
|
const COUNT: usize = 1024;
|
||||||
for _ in 0..COUNT {
|
for _ in 0..COUNT {
|
||||||
let (_, pk) = s.generate_keypair(&mut thread_rng());
|
let (_, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let hash = hash(&pk);
|
let hash = hash(&pk);
|
||||||
assert!(!set.contains(&hash));
|
assert!(!set.contains(&hash));
|
||||||
set.insert(hash);
|
set.insert(hash);
|
||||||
|
@ -2050,12 +2034,12 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn create_pubkey_combine() {
|
fn create_pubkey_combine() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
|
let (sk1, pk1) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
|
let (sk2, pk2) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sum1 = pk1.combine(&pk2);
|
let sum1 = pk1.combine(&pk2);
|
||||||
assert!(sum1.is_ok());
|
assert!(sum1.is_ok());
|
||||||
|
@ -2095,7 +2079,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "serde", feature = "alloc"))]
|
||||||
fn test_serde() {
|
fn test_serde() {
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -2160,7 +2144,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn test_tweak_add_then_tweak_add_check() {
|
fn test_tweak_add_then_tweak_add_check() {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -2168,7 +2152,7 @@ mod test {
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let tweak = Scalar::random();
|
let tweak = Scalar::random();
|
||||||
|
|
||||||
let kp = KeyPair::new(&s, &mut thread_rng());
|
let kp = KeyPair::new(&s, &mut rand::thread_rng());
|
||||||
let (xonly, _) = XOnlyPublicKey::from_keypair(&kp);
|
let (xonly, _) = XOnlyPublicKey::from_keypair(&kp);
|
||||||
|
|
||||||
let tweaked_kp = kp.add_xonly_tweak(&s, &tweak).expect("keypair tweak add failed");
|
let tweaked_kp = kp.add_xonly_tweak(&s, &tweak).expect("keypair tweak add failed");
|
||||||
|
@ -2259,7 +2243,7 @@ mod test {
|
||||||
assert_tokens(&sk.readable(), &[Token::String(SK_STR)]);
|
assert_tokens(&sk.readable(), &[Token::String(SK_STR)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn keys() -> (SecretKey, PublicKey, KeyPair, XOnlyPublicKey) {
|
fn keys() -> (SecretKey, PublicKey, KeyPair, XOnlyPublicKey) {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -2292,7 +2276,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn convert_public_key_to_xonly_public_key() {
|
fn convert_public_key_to_xonly_public_key() {
|
||||||
let (_sk, pk, _kp, want) = keys();
|
let (_sk, pk, _kp, want) = keys();
|
||||||
let (got, parity) = pk.x_only_public_key();
|
let (got, parity) = pk.x_only_public_key();
|
||||||
|
@ -2302,7 +2286,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn convert_secret_key_to_public_key() {
|
fn convert_secret_key_to_public_key() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -2313,7 +2297,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn convert_secret_key_to_x_only_public_key() {
|
fn convert_secret_key_to_x_only_public_key() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -2325,7 +2309,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn convert_keypair_to_public_key() {
|
fn convert_keypair_to_public_key() {
|
||||||
let (_sk, want, kp, _xonly) = keys();
|
let (_sk, want, kp, _xonly) = keys();
|
||||||
let got = kp.public_key();
|
let got = kp.public_key();
|
||||||
|
@ -2334,7 +2318,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn convert_keypair_to_x_only_public_key() {
|
fn convert_keypair_to_x_only_public_key() {
|
||||||
let (_sk, _pk, kp, want) = keys();
|
let (_sk, _pk, kp, want) = keys();
|
||||||
let (got, parity) = kp.x_only_public_key();
|
let (got, parity) = kp.x_only_public_key();
|
||||||
|
@ -2345,7 +2329,7 @@ mod test {
|
||||||
|
|
||||||
// SecretKey -> KeyPair -> SecretKey
|
// SecretKey -> KeyPair -> SecretKey
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn roundtrip_secret_key_via_keypair() {
|
fn roundtrip_secret_key_via_keypair() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let (sk, _pk, _kp, _xonly) = keys();
|
let (sk, _pk, _kp, _xonly) = keys();
|
||||||
|
@ -2358,7 +2342,7 @@ mod test {
|
||||||
|
|
||||||
// KeyPair -> SecretKey -> KeyPair
|
// KeyPair -> SecretKey -> KeyPair
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn roundtrip_keypair_via_secret_key() {
|
fn roundtrip_keypair_via_secret_key() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let (_sk, _pk, kp, _xonly) = keys();
|
let (_sk, _pk, kp, _xonly) = keys();
|
||||||
|
@ -2371,7 +2355,7 @@ mod test {
|
||||||
|
|
||||||
// XOnlyPublicKey -> PublicKey -> XOnlyPublicKey
|
// XOnlyPublicKey -> PublicKey -> XOnlyPublicKey
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn roundtrip_x_only_public_key_via_public_key() {
|
fn roundtrip_x_only_public_key_via_public_key() {
|
||||||
let (_sk, _pk, _kp, xonly) = keys();
|
let (_sk, _pk, _kp, xonly) = keys();
|
||||||
|
|
||||||
|
@ -2384,7 +2368,7 @@ mod test {
|
||||||
|
|
||||||
// PublicKey -> XOnlyPublicKey -> PublicKey
|
// PublicKey -> XOnlyPublicKey -> PublicKey
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
fn roundtrip_public_key_via_x_only_public_key() {
|
fn roundtrip_public_key_via_x_only_public_key() {
|
||||||
let (_sk, pk, _kp, _xonly) = keys();
|
let (_sk, pk, _kp, _xonly) = keys();
|
||||||
|
|
||||||
|
@ -2444,10 +2428,12 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "global-context"))]
|
#[cfg(all(feature = "rand-std", feature = "bitcoin-hashes-std"))]
|
||||||
fn test_keypair_from_str() {
|
fn test_keypair_from_str() {
|
||||||
|
use bitcoin_hashes::hex::ToHex;
|
||||||
|
|
||||||
let ctx = crate::Secp256k1::new();
|
let ctx = crate::Secp256k1::new();
|
||||||
let keypair = KeyPair::new(&ctx, &mut thread_rng());
|
let keypair = KeyPair::new(&ctx, &mut rand::thread_rng());
|
||||||
let msg = keypair.secret_key().secret_bytes().to_hex();
|
let msg = keypair.secret_key().secret_bytes().to_hex();
|
||||||
let parsed_key: KeyPair = msg.parse().unwrap();
|
let parsed_key: KeyPair = msg.parse().unwrap();
|
||||||
assert_eq!(parsed_key, keypair);
|
assert_eq!(parsed_key, keypair);
|
||||||
|
|
119
src/lib.rs
119
src/lib.rs
|
@ -41,7 +41,7 @@
|
||||||
//! trigger any assertion failures in the upstream library.
|
//! trigger any assertion failures in the upstream library.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # #[cfg(all(feature = "std", feature="rand-std", feature="bitcoin-hashes-std"))] {
|
//! # #[cfg(all(feature = "rand-std", feature = "bitcoin-hashes-std"))] {
|
||||||
//! use secp256k1::rand::rngs::OsRng;
|
//! use secp256k1::rand::rngs::OsRng;
|
||||||
//! use secp256k1::{Secp256k1, Message};
|
//! use secp256k1::{Secp256k1, Message};
|
||||||
//! use secp256k1::hashes::sha256;
|
//! use secp256k1::hashes::sha256;
|
||||||
|
@ -58,12 +58,11 @@
|
||||||
//! If the "global-context" feature is enabled you have access to an alternate API.
|
//! If the "global-context" feature is enabled you have access to an alternate API.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # #[cfg(all(feature = "global-context", feature = "std", feature = "rand-std", feature = "bitcoin-hashes-std"))] {
|
//! # #[cfg(all(feature = "global-context", feature = "bitcoin-hashes-std", feature = "rand-std"))] {
|
||||||
//! use secp256k1::rand::thread_rng;
|
|
||||||
//! use secp256k1::{generate_keypair, Message};
|
//! use secp256k1::{generate_keypair, Message};
|
||||||
//! use secp256k1::hashes::sha256;
|
//! use secp256k1::hashes::sha256;
|
||||||
//!
|
//!
|
||||||
//! let (secret_key, public_key) = generate_keypair(&mut thread_rng());
|
//! let (secret_key, public_key) = generate_keypair(&mut rand::thread_rng());
|
||||||
//! let message = Message::from_hashed_data::<sha256::Hash>("Hello World!".as_bytes());
|
//! let message = Message::from_hashed_data::<sha256::Hash>("Hello World!".as_bytes());
|
||||||
//!
|
//!
|
||||||
//! let sig = secret_key.sign_ecdsa(message);
|
//! let sig = secret_key.sign_ecdsa(message);
|
||||||
|
@ -76,7 +75,7 @@
|
||||||
//! Alternately, keys and messages can be parsed from slices, like
|
//! Alternately, keys and messages can be parsed from slices, like
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # #[cfg(any(feature = "alloc", features = "std"))] {
|
//! # #[cfg(feature = "alloc")] {
|
||||||
//! use secp256k1::{Secp256k1, Message, SecretKey, PublicKey};
|
//! use secp256k1::{Secp256k1, Message, SecretKey, PublicKey};
|
||||||
//!
|
//!
|
||||||
//! let secp = Secp256k1::new();
|
//! let secp = Secp256k1::new();
|
||||||
|
@ -94,7 +93,7 @@
|
||||||
//! Users who only want to verify signatures can use a cheaper context, like so:
|
//! Users who only want to verify signatures can use a cheaper context, like so:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # #[cfg(any(feature = "alloc", feature = "std"))] {
|
//! # #[cfg(feature = "alloc")] {
|
||||||
//! use secp256k1::{Secp256k1, Message, ecdsa, PublicKey};
|
//! use secp256k1::{Secp256k1, Message, ecdsa, PublicKey};
|
||||||
//!
|
//!
|
||||||
//! let secp = Secp256k1::verification_only();
|
//! let secp = Secp256k1::verification_only();
|
||||||
|
@ -190,7 +189,7 @@ pub use bitcoin_hashes as hashes;
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
|
||||||
pub use context::global::SECP256K1;
|
pub use context::global::SECP256K1;
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub use rand;
|
pub use rand;
|
||||||
pub use secp256k1_sys as ffi;
|
pub use secp256k1_sys as ffi;
|
||||||
|
@ -258,12 +257,12 @@ impl Message {
|
||||||
|
|
||||||
/// Constructs a [`Message`] by hashing `data` with hash algorithm `H`.
|
/// Constructs a [`Message`] by hashing `data` with hash algorithm `H`.
|
||||||
///
|
///
|
||||||
/// Requires the feature `bitcoin_hashes` to be enabled.
|
/// Requires the feature `bitcoin-hashes` to be enabled.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature="bitcoin_hashes")] {
|
/// # #[cfg(feature = "bitcoin-hashes")] {
|
||||||
/// use secp256k1::hashes::{sha256, Hash};
|
/// use secp256k1::hashes::{sha256, Hash};
|
||||||
/// use secp256k1::Message;
|
/// use secp256k1::Message;
|
||||||
///
|
///
|
||||||
|
@ -421,7 +420,7 @@ impl<C: Context> Secp256k1<C> {
|
||||||
///
|
///
|
||||||
/// Requires compilation with "rand" feature. See comment by Gregory Maxwell in
|
/// Requires compilation with "rand" feature. See comment by Gregory Maxwell in
|
||||||
/// [libsecp256k1](https://github.com/bitcoin-core/secp256k1/commit/d2275795ff22a6f4738869f5528fbbb61738aa48).
|
/// [libsecp256k1](https://github.com/bitcoin-core/secp256k1/commit/d2275795ff22a6f4738869f5528fbbb61738aa48).
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub fn randomize<R: rand::Rng + ?Sized>(&mut self, rng: &mut R) {
|
pub fn randomize<R: rand::Rng + ?Sized>(&mut self, rng: &mut R) {
|
||||||
let mut seed = [0u8; 32];
|
let mut seed = [0u8; 32];
|
||||||
|
@ -452,7 +451,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
/// Generates a random keypair. Convenience function for [`SecretKey::new`] and
|
/// Generates a random keypair. Convenience function for [`SecretKey::new`] and
|
||||||
/// [`PublicKey::from_secret_key`].
|
/// [`PublicKey::from_secret_key`].
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub fn generate_keypair<R: rand::Rng + ?Sized>(
|
pub fn generate_keypair<R: rand::Rng + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -521,20 +520,27 @@ fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
|
||||||
return unsafe { Ok(str::from_utf8_unchecked(result)) };
|
return unsafe { Ok(str::from_utf8_unchecked(result)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rand")]
|
||||||
|
pub(crate) fn random_32_bytes<R: rand::Rng + ?Sized>(rng: &mut R) -> [u8; 32] {
|
||||||
|
let mut ret = [0u8; 32];
|
||||||
|
rng.fill(&mut ret);
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::marker::PhantomData;
|
#[allow(unused_imports)] // When building with no default features.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
use crate::context::*;
|
#[cfg(feature = "alloc")]
|
||||||
use crate::ffi::types::AlignedType;
|
use crate::{ffi, PublicKey, Secp256k1, SecretKey};
|
||||||
use crate::ffi::{self};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants, ecdsa, from_hex, to_hex, Error, Message, PublicKey, Secp256k1, SecretKey,
|
constants, ecdsa, from_hex, Error, Message,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! hex {
|
macro_rules! hex {
|
||||||
|
@ -546,8 +552,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "rand-std")]
|
||||||
fn test_manual_create_destroy() {
|
fn test_manual_create_destroy() {
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
let ctx_full = unsafe { ffi::secp256k1_context_create(AllPreallocated::FLAGS) };
|
let ctx_full = unsafe { ffi::secp256k1_context_create(AllPreallocated::FLAGS) };
|
||||||
let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) };
|
let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) };
|
||||||
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
|
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
|
||||||
|
@ -560,7 +568,7 @@ mod tests {
|
||||||
let vrfy: Secp256k1<VerifyOnlyPreallocated> =
|
let vrfy: Secp256k1<VerifyOnlyPreallocated> =
|
||||||
Secp256k1 { ctx: ctx_vrfy, phantom: PhantomData, size };
|
Secp256k1 { ctx: ctx_vrfy, phantom: PhantomData, size };
|
||||||
|
|
||||||
let (sk, pk) = full.generate_keypair(&mut thread_rng());
|
let (sk, pk) = full.generate_keypair(&mut rand::thread_rng());
|
||||||
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
||||||
// Try signing
|
// Try signing
|
||||||
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
||||||
|
@ -580,7 +588,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn test_raw_ctx() {
|
fn test_raw_ctx() {
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
|
|
||||||
|
@ -592,7 +600,7 @@ mod tests {
|
||||||
let mut sign = unsafe { Secp256k1::from_raw_signing_only(ctx_sign.ctx) };
|
let mut sign = unsafe { Secp256k1::from_raw_signing_only(ctx_sign.ctx) };
|
||||||
let mut vrfy = unsafe { Secp256k1::from_raw_verification_only(ctx_vrfy.ctx) };
|
let mut vrfy = unsafe { Secp256k1::from_raw_verification_only(ctx_vrfy.ctx) };
|
||||||
|
|
||||||
let (sk, pk) = full.generate_keypair(&mut thread_rng());
|
let (sk, pk) = full.generate_keypair(&mut rand::thread_rng());
|
||||||
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
||||||
// Try signing
|
// Try signing
|
||||||
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
||||||
|
@ -615,7 +623,7 @@ mod tests {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore] // Panicking from C may trap (SIGILL) intentionally, so we test this manually.
|
#[ignore] // Panicking from C may trap (SIGILL) intentionally, so we test this manually.
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "alloc")]
|
||||||
fn test_panic_raw_ctx_should_terminate_abnormally() {
|
fn test_panic_raw_ctx_should_terminate_abnormally() {
|
||||||
// Trying to use an all-zeros public key should cause an ARG_CHECK to trigger.
|
// Trying to use an all-zeros public key should cause an ARG_CHECK to trigger.
|
||||||
let pk = PublicKey::from(unsafe { ffi::PublicKey::new() });
|
let pk = PublicKey::from(unsafe { ffi::PublicKey::new() });
|
||||||
|
@ -623,7 +631,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "rand-std")]
|
||||||
fn test_preallocation() {
|
fn test_preallocation() {
|
||||||
|
use crate::ffi::types::AlignedType;
|
||||||
|
|
||||||
let mut buf_ful = vec![AlignedType::zeroed(); Secp256k1::preallocate_size()];
|
let mut buf_ful = vec![AlignedType::zeroed(); Secp256k1::preallocate_size()];
|
||||||
let mut buf_sign = vec![AlignedType::zeroed(); Secp256k1::preallocate_signing_size()];
|
let mut buf_sign = vec![AlignedType::zeroed(); Secp256k1::preallocate_signing_size()];
|
||||||
let mut buf_vfy = vec![AlignedType::zeroed(); Secp256k1::preallocate_verification_size()];
|
let mut buf_vfy = vec![AlignedType::zeroed(); Secp256k1::preallocate_verification_size()];
|
||||||
|
@ -635,7 +646,7 @@ mod tests {
|
||||||
// drop(buf_vfy); // The buffer can't get dropped before the context.
|
// drop(buf_vfy); // The buffer can't get dropped before the context.
|
||||||
// println!("{:?}", buf_ful[5]); // Can't even read the data thanks to the borrow checker.
|
// println!("{:?}", buf_ful[5]); // Can't even read the data thanks to the borrow checker.
|
||||||
|
|
||||||
let (sk, pk) = full.generate_keypair(&mut thread_rng());
|
let (sk, pk) = full.generate_keypair(&mut rand::thread_rng());
|
||||||
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
||||||
// Try signing
|
// Try signing
|
||||||
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
||||||
|
@ -647,18 +658,17 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn capabilities() {
|
fn capabilities() {
|
||||||
let sign = Secp256k1::signing_only();
|
let sign = Secp256k1::signing_only();
|
||||||
let vrfy = Secp256k1::verification_only();
|
let vrfy = Secp256k1::verification_only();
|
||||||
let full = Secp256k1::new();
|
let full = Secp256k1::new();
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
// Try key generation
|
// Try key generation
|
||||||
let (sk, pk) = full.generate_keypair(&mut thread_rng());
|
let (sk, pk) = full.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
// Try signing
|
// Try signing
|
||||||
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
assert_eq!(sign.sign_ecdsa(&msg, &sk), full.sign_ecdsa(&msg, &sk));
|
||||||
|
@ -677,17 +687,16 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn signature_serialize_roundtrip() {
|
fn signature_serialize_roundtrip() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
thread_rng().fill_bytes(&mut msg);
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
let (sk, _) = s.generate_keypair(&mut thread_rng());
|
let (sk, _) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let sig1 = s.sign_ecdsa(&msg, &sk);
|
let sig1 = s.sign_ecdsa(&msg, &sk);
|
||||||
let der = sig1.serialize_der();
|
let der = sig1.serialize_der();
|
||||||
let sig2 = ecdsa::Signature::from_der(&der[..]).unwrap();
|
let sig2 = ecdsa::Signature::from_der(&der[..]).unwrap();
|
||||||
|
@ -768,18 +777,17 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn sign_and_verify_ecdsa() {
|
fn sign_and_verify_ecdsa() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
|
||||||
let noncedata = [42u8; 32];
|
let noncedata = [42u8; 32];
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
thread_rng().fill_bytes(&mut msg);
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let sig = s.sign_ecdsa(&msg, &sk);
|
let sig = s.sign_ecdsa(&msg, &sk);
|
||||||
assert_eq!(s.verify_ecdsa(&msg, &sig, &pk), Ok(()));
|
assert_eq!(s.verify_ecdsa(&msg, &sig, &pk), Ok(()));
|
||||||
let noncedata_sig = s.sign_ecdsa_with_noncedata(&msg, &sk, &noncedata);
|
let noncedata_sig = s.sign_ecdsa_with_noncedata(&msg, &sk, &noncedata);
|
||||||
|
@ -803,10 +811,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn sign_and_verify_extreme() {
|
fn sign_and_verify_extreme() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
// Wild keys: 1, CURVE_ORDER - 1
|
// Wild keys: 1, CURVE_ORDER - 1
|
||||||
// Wild msgs: 1, CURVE_ORDER - 1
|
// Wild msgs: 1, CURVE_ORDER - 1
|
||||||
|
@ -837,21 +845,19 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn sign_and_verify_fail() {
|
fn sign_and_verify_fail() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut rand::thread_rng());
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
let sig = s.sign_ecdsa(&msg, &sk);
|
let sig = s.sign_ecdsa(&msg, &sk);
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
assert_eq!(s.verify_ecdsa(&msg, &sig, &pk), Err(Error::IncorrectSignature));
|
assert_eq!(s.verify_ecdsa(&msg, &sig, &pk), Err(Error::IncorrectSignature));
|
||||||
}
|
}
|
||||||
|
@ -880,8 +886,12 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "rand-std")]
|
||||||
fn test_hex() {
|
fn test_hex() {
|
||||||
let mut rng = thread_rng();
|
use super::to_hex;
|
||||||
|
use rand::RngCore;
|
||||||
|
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
const AMOUNT: usize = 1024;
|
const AMOUNT: usize = 1024;
|
||||||
for i in 0..AMOUNT {
|
for i in 0..AMOUNT {
|
||||||
// 255 isn't a valid utf8 character.
|
// 255 isn't a valid utf8 character.
|
||||||
|
@ -1050,15 +1060,14 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(bench)]
|
#[cfg(bench)]
|
||||||
|
#[cfg(feature = "rand-std")]
|
||||||
mod benches {
|
mod benches {
|
||||||
use rand::rngs::mock::StepRng;
|
use rand::rngs::mock::StepRng;
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
use test::{black_box, Bencher};
|
use test::{black_box, Bencher};
|
||||||
|
|
||||||
use super::{Message, Secp256k1};
|
use super::{Message, Secp256k1};
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
|
||||||
pub fn generate(bh: &mut Bencher) {
|
pub fn generate(bh: &mut Bencher) {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let mut r = StepRng::new(1, 1);
|
let mut r = StepRng::new(1, 1);
|
||||||
|
@ -1070,13 +1079,11 @@ mod benches {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
|
||||||
pub fn bench_sign_ecdsa(bh: &mut Bencher) {
|
pub fn bench_sign_ecdsa(bh: &mut Bencher) {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
let (sk, _) = s.generate_keypair(&mut thread_rng());
|
let (sk, _) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
|
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
let sig = s.sign_ecdsa(&msg, &sk);
|
let sig = s.sign_ecdsa(&msg, &sk);
|
||||||
|
@ -1085,13 +1092,11 @@ mod benches {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
|
||||||
pub fn bench_verify_ecdsa(bh: &mut Bencher) {
|
pub fn bench_verify_ecdsa(bh: &mut Bencher) {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let mut msg = [0u8; 32];
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
thread_rng().fill_bytes(&mut msg);
|
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut rand::thread_rng());
|
||||||
let sig = s.sign_ecdsa(&msg, &sk);
|
let sig = s.sign_ecdsa(&msg, &sk);
|
||||||
|
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
|
|
|
@ -37,12 +37,12 @@ impl Scalar {
|
||||||
pub const MAX: Scalar = Scalar(MAX_RAW);
|
pub const MAX: Scalar = Scalar(MAX_RAW);
|
||||||
|
|
||||||
/// Generates a random scalar
|
/// Generates a random scalar
|
||||||
#[cfg(any(test, feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
|
||||||
pub fn random() -> Self { Self::random_custom(rand::thread_rng()) }
|
pub fn random() -> Self { Self::random_custom(rand::thread_rng()) }
|
||||||
|
|
||||||
/// Generates a random scalar using supplied RNG
|
/// Generates a random scalar using supplied RNG
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub fn random_custom<R: rand::Rng>(mut rng: R) -> Self {
|
pub fn random_custom<R: rand::Rng>(mut rng: R) -> Self {
|
||||||
let mut bytes = [0u8; 32];
|
let mut bytes = [0u8; 32];
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
use core::{fmt, ptr, str};
|
use core::{fmt, ptr, str};
|
||||||
|
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
|
|
||||||
use crate::ffi::{self, impl_array_newtype, CPtr};
|
use crate::ffi::{self, impl_array_newtype, CPtr};
|
||||||
use crate::key::{KeyPair, XOnlyPublicKey};
|
use crate::key::{KeyPair, XOnlyPublicKey};
|
||||||
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
#[cfg(feature = "global-context")]
|
||||||
use crate::SECP256K1;
|
use crate::SECP256K1;
|
||||||
use crate::{constants, from_hex, Error, Message, Secp256k1, Signing, Verification};
|
use crate::{constants, from_hex, Error, Message, Secp256k1, Signing, Verification};
|
||||||
|
|
||||||
|
@ -86,8 +86,8 @@ impl Signature {
|
||||||
|
|
||||||
/// Verifies a schnorr signature for `msg` using `pk` and the global [`SECP256K1`] context.
|
/// Verifies a schnorr signature for `msg` using `pk` and the global [`SECP256K1`] context.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
#[cfg(feature = "global-context")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "rand-std"))))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
|
||||||
pub fn verify(&self, msg: &Message, pk: &XOnlyPublicKey) -> Result<(), Error> {
|
pub fn verify(&self, msg: &Message, pk: &XOnlyPublicKey) -> Result<(), Error> {
|
||||||
SECP256K1.verify_schnorr(self, msg, pk)
|
SECP256K1.verify_schnorr(self, msg, pk)
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
|
|
||||||
/// Create a schnorr signature internally using the ThreadRng random number
|
/// Create a schnorr signature internally using the ThreadRng random number
|
||||||
/// generator to generate the auxiliary random data.
|
/// generator to generate the auxiliary random data.
|
||||||
#[cfg(any(test, feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
|
||||||
pub fn sign_schnorr(&self, msg: &Message, keypair: &KeyPair) -> Signature {
|
pub fn sign_schnorr(&self, msg: &Message, keypair: &KeyPair) -> Signature {
|
||||||
self.sign_schnorr_with_rng(msg, keypair, &mut rand::thread_rng())
|
self.sign_schnorr_with_rng(msg, keypair, &mut rand::thread_rng())
|
||||||
|
@ -142,7 +142,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
|
|
||||||
/// Create a schnorr signature using the given random number generator to
|
/// Create a schnorr signature using the given random number generator to
|
||||||
/// generate the auxiliary random data.
|
/// generate the auxiliary random data.
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(feature = "rand")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub fn sign_schnorr_with_rng<R: Rng + CryptoRng>(
|
pub fn sign_schnorr_with_rng<R: Rng + CryptoRng>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -187,8 +187,8 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
|
#[cfg(feature = "rand-std")]
|
||||||
use rand::rngs::ThreadRng;
|
use rand::rngs::ThreadRng;
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ mod tests {
|
||||||
use crate::Error::InvalidPublicKey;
|
use crate::Error::InvalidPublicKey;
|
||||||
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
|
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
|
||||||
|
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), feature = "alloc"))]
|
||||||
macro_rules! hex_32 {
|
macro_rules! hex_32 {
|
||||||
($hex:expr) => {{
|
($hex:expr) => {{
|
||||||
let mut result = [0u8; 32];
|
let mut result = [0u8; 32];
|
||||||
|
@ -207,45 +207,42 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn schnorr_sign_with_aux_rand_verify() {
|
fn schnorr_sign_with_aux_rand_verify() {
|
||||||
sign_helper(|secp, msg, seckey, rng| {
|
sign_helper(|secp, msg, seckey, rng| {
|
||||||
let mut aux_rand = [0u8; 32];
|
let aux_rand = crate::random_32_bytes(rng);
|
||||||
rng.fill_bytes(&mut aux_rand);
|
|
||||||
secp.sign_schnorr_with_aux_rand(msg, seckey, &aux_rand)
|
secp.sign_schnorr_with_aux_rand(msg, seckey, &aux_rand)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn schnor_sign_with_rng_verify() {
|
fn schnor_sign_with_rng_verify() {
|
||||||
sign_helper(|secp, msg, seckey, mut rng| secp.sign_schnorr_with_rng(msg, seckey, &mut rng))
|
sign_helper(|secp, msg, seckey, rng| secp.sign_schnorr_with_rng(msg, seckey, rng))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn schnorr_sign_verify() { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr(msg, seckey)) }
|
fn schnorr_sign_verify() { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr(msg, seckey)) }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn schnorr_sign_no_aux_rand_verify() {
|
fn schnorr_sign_no_aux_rand_verify() {
|
||||||
sign_helper(|secp, msg, seckey, _| secp.sign_schnorr_no_aux_rand(msg, seckey))
|
sign_helper(|secp, msg, seckey, _| secp.sign_schnorr_no_aux_rand(msg, seckey))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn sign_helper(
|
fn sign_helper(
|
||||||
sign: fn(&Secp256k1<crate::All>, &Message, &KeyPair, &mut ThreadRng) -> Signature,
|
sign: fn(&Secp256k1<crate::All>, &Message, &KeyPair, &mut ThreadRng) -> Signature,
|
||||||
) {
|
) {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let kp = KeyPair::new(&secp, &mut rng);
|
let kp = KeyPair::new(&secp, &mut rng);
|
||||||
let (pk, _parity) = kp.x_only_public_key();
|
let (pk, _parity) = kp.x_only_public_key();
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
|
||||||
|
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
rng.fill_bytes(&mut msg);
|
let msg = crate::random_32_bytes(&mut rand::thread_rng());
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
|
|
||||||
let sig = sign(&secp, &msg, &kp, &mut rng);
|
let sig = sign(&secp, &msg, &kp, &mut rng);
|
||||||
|
@ -255,7 +252,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "alloc")]
|
||||||
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
fn schnorr_sign() {
|
fn schnorr_sign() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
@ -278,7 +275,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "alloc")]
|
||||||
fn schnorr_verify() {
|
fn schnorr_verify() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -306,10 +303,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "rand-std")]
|
||||||
fn test_pubkey_serialize_roundtrip() {
|
fn test_pubkey_serialize_roundtrip() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let kp = KeyPair::new(&secp, &mut thread_rng());
|
let kp = KeyPair::new(&secp, &mut rand::thread_rng());
|
||||||
let (pk, _parity) = kp.x_only_public_key();
|
let (pk, _parity) = kp.x_only_public_key();
|
||||||
|
|
||||||
let ser = pk.serialize();
|
let ser = pk.serialize();
|
||||||
|
@ -318,7 +315,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(feature = "alloc")]
|
||||||
fn test_xonly_key_extraction() {
|
fn test_xonly_key_extraction() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let sk_str = "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF";
|
let sk_str = "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF";
|
||||||
|
@ -426,7 +423,7 @@ mod tests {
|
||||||
// In fuzzing mode secret->public key derivation is different, so
|
// In fuzzing mode secret->public key derivation is different, so
|
||||||
// this test will never correctly derive the static pubkey.
|
// this test will never correctly derive the static pubkey.
|
||||||
#[cfg(not(fuzzing))]
|
#[cfg(not(fuzzing))]
|
||||||
#[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "rand", feature = "alloc"))]
|
||||||
fn test_pubkey_serialize() {
|
fn test_pubkey_serialize() {
|
||||||
use rand::rngs::mock::StepRng;
|
use rand::rngs::mock::StepRng;
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
@ -443,7 +440,7 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "serde", feature = "alloc"))]
|
||||||
fn test_serde() {
|
fn test_serde() {
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue