Merge rust-bitcoin/rust-secp256k1#331: Update the code to edition 2018, and update dependencies

5d2f1ceb64 Fix WASM build (Elichai Turkel)
39aaac6834 Use new trait TryFrom and do small refactoring (Elichai Turkel)
7d3a149ca5 Move more things from the std feature to the alloc feature (Elichai Turkel)
bc8c713631 Replace c_void with core::ffi::c_void (Elichai Turkel)
26a52bc8c8 Update secp256k1-sys to edition 2018 and fix imports (Elichai Turkel)
ebe46a4d4e Update rand to 0.8 and replace CounterRng with mock::StepRng (Elichai Turkel)
626835f540 Update secp256k1 to edition 2018 and fix imports (Elichai Turkel)
67c0922a46 Update MSRV in CI and Readme from 1.29 to 1.41 (Elichai Turkel)

Pull request description:

  As proposed in https://github.com/rust-bitcoin/rust-bitcoin/issues/510#issuecomment-881686342 this PR raises the MSRV to 1.41.1 it also changes the code to be Edition 2018.

  The PR contains a few things:
  * Moving to edition 2018 and fixing the imports
  * Sorting and combining imports to make them more concise
  * Replacing our c_void with `core::ffi::c_void`
  * Bumping the `rand` version to latest and modifying our `RngCore` implementations accordingly
  * Doing some small refactoring and using the new `TryInto` trait where it makes the code nicer

  If people prefer I can split this PR into multiple and/or drop some commits

ACKs for top commit:
  tcharding:
    ACK 5d2f1ceb64
  apoelstra:
    ACK 5d2f1ceb64

Tree-SHA512: 5bf84e7ebb6286d59f8cada0bb712c46336f0dd6c35b67e6f4ba323b5484ad925b99b73e778ae4608f123938e7ee8705a0aec576cd9c065072c4ecf1248e3470
This commit is contained in:
Andrew Poelstra 2022-06-08 20:52:38 +00:00
commit 4f7f138797
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
19 changed files with 258 additions and 416 deletions

View File

@ -36,7 +36,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
rust: [stable, beta, nightly, 1.29.0]
rust: [stable, beta, nightly, 1.41.1]
steps:
- name: Checkout Crate
uses: actions/checkout@v2
@ -46,9 +46,6 @@ jobs:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- name: Pin cc if rust 1.29
if: matrix.rust == '1.29.0'
run: cargo generate-lockfile --verbose && cargo update -p cc --precise "1.0.41" --verbose
- name: Running cargo
env:
DO_FEATURE_MATRIX: true
@ -59,7 +56,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
rust: [stable, beta, nightly] # No 1.29 because WASM requires Rust 1.30
rust: [stable, beta, nightly] # wasm-pack doesn't support rust 1.41.1
steps:
- name: Checkout Crate
uses: actions/checkout@v2

View File

@ -10,7 +10,7 @@ documentation = "https://docs.rs/secp256k1/"
description = "Rust wrapper library for Pieter Wuille's `libsecp256k1`. Implements ECDSA and BIP 340 signatures for the SECG elliptic curve group secp256k1 and related utilities."
keywords = [ "crypto", "ECDSA", "secp256k1", "libsecp256k1", "bitcoin" ]
readme = "README.md"
autoexamples = false # Remove when edition 2018 https://github.com/rust-lang/cargo/issues/5330
edition = "2018"
# Should make docs.rs show all functions, even those behind non-default features
[package.metadata.docs.rs]
@ -20,9 +20,9 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
unstable = ["recovery", "rand-std"]
default = ["std"]
std = ["secp256k1-sys/std"]
std = ["alloc", "secp256k1-sys/std"]
# allow use of Secp256k1::new and related API that requires an allocator
alloc = []
alloc = ["secp256k1-sys/alloc"]
bitcoin-hashes-std = ["bitcoin_hashes/std"]
rand-std = ["rand/std"]
recovery = ["secp256k1-sys/recovery"]
@ -43,17 +43,17 @@ serde = { version = "1.0", default-features = false, optional = true }
# You likely only want to enable these if you explicitly do not want to use "std", otherwise enable
# the respective -std feature e.g., bitcoin-hashes-std
bitcoin_hashes = { version = "0.10", default-features = false, optional = true }
rand = { version = "0.6", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, optional = true }
[dev-dependencies]
rand = "0.6"
rand_core = "0.4"
rand = "0.8"
rand_core = "0.6"
serde_test = "1.0"
bitcoin_hashes = "0.10"
[target.wasm32-unknown-unknown.dev-dependencies]
wasm-bindgen-test = "0.3"
rand = { version = "0.6", features = ["wasm-bindgen"] }
getrandom = { version = "0.2", features = ["js"] }
[[example]]

View File

@ -20,21 +20,7 @@ Contributions to this library are welcome. A few guidelines:
* Any breaking changes must have an accompanied entry in CHANGELOG.md
* No new dependencies, please.
* No crypto should be implemented in Rust, with the possible exception of hash functions. Cryptographic contributions should be directed upstream to libsecp256k1.
* This library should always compile with any combination of features on **Rust 1.29**.
## A note on Rust 1.29 support
The build dependency `cc` might require a more recent version of the Rust compiler.
To ensure compilation with Rust 1.29.0, pin its version in your `Cargo.lock`
with `cargo update -p cc --precise 1.0.41`. If you're using `secp256k1` in a library,
to make sure it compiles in CI, you'll need to generate a lockfile first.
Example for Travis CI:
```yml
before_script:
- if [ "$TRAVIS_RUST_VERSION" == "1.29.0" ]; then
cargo generate-lockfile --verbose && cargo update -p cc --precise "1.0.41" --verbose;
fi
```
* This library should always compile with any combination of features on **Rust 1.41.1**.
## Fuzzing

View File

@ -1 +1 @@
msrv = "1.29"
msrv = "1.41.1"

View File

@ -1,11 +1,11 @@
extern crate secp256k1;
use secp256k1::rand::rngs::OsRng;
use secp256k1::rand::thread_rng;
use secp256k1::{PublicKey, Secp256k1, SecretKey};
fn main() {
let secp = Secp256k1::new();
let mut rng = OsRng::new().unwrap();
let mut rng = thread_rng();
// First option:
let (seckey, pubkey) = secp.generate_keypair(&mut rng);

View File

@ -13,6 +13,7 @@ keywords = [ "secp256k1", "libsecp256k1", "ffi" ]
readme = "README.md"
build = "build.rs"
links = "rustsecp256k1_v0_5_0"
edition = "2018"
# Should make docs.rs show all functions, even those behind non-default features
[package.metadata.docs.rs]
@ -29,5 +30,6 @@ libc = "0.2"
default = ["std"]
recovery = []
lowmemory = []
std = []
std = ["alloc"]
alloc = []

View File

@ -17,10 +17,7 @@
//! not be needed for most users.
// Coding conventions
#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case, unused_mut)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
@ -28,10 +25,12 @@
#[cfg(any(test, feature = "std"))]
extern crate core;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(fuzzing)]
const THIS_UNUSED_CONSTANT_IS_YOUR_WARNING_THAT_ALL_THE_CRYPTO_IN_THIS_LIB_IS_DISABLED_FOR_FUZZING: usize = 0;
#[macro_use]
mod macros;
pub mod types;
@ -585,11 +584,11 @@ extern "C" {
///
/// The newly created secp256k1 raw context.
#[no_mangle]
#[cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))))]
#[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))))]
pub unsafe extern "C" fn rustsecp256k1_v0_5_0_context_create(flags: c_uint) -> *mut Context {
use core::mem;
use std::alloc;
use crate::alloc::alloc;
assert!(ALIGN_TO >= mem::align_of::<usize>());
assert!(ALIGN_TO >= mem::align_of::<&usize>());
assert!(ALIGN_TO >= mem::size_of::<usize>());
@ -605,8 +604,8 @@ pub unsafe extern "C" fn rustsecp256k1_v0_5_0_context_create(flags: c_uint) -> *
secp256k1_context_preallocated_create(ptr, flags)
}
#[cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))))]
#[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))))]
pub unsafe fn secp256k1_context_create(flags: c_uint) -> *mut Context {
rustsecp256k1_v0_5_0_context_create(flags)
}
@ -618,10 +617,10 @@ pub unsafe fn secp256k1_context_create(flags: c_uint) -> *mut Context {
/// The pointer shouldn't be used after passing to this function, consider it as passing it to `free()`.
///
#[no_mangle]
#[cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))))]
#[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))))]
pub unsafe extern "C" fn rustsecp256k1_v0_5_0_context_destroy(ctx: *mut Context) {
use std::alloc;
use crate::alloc::alloc;
secp256k1_context_preallocated_destroy(ctx);
let ptr = (ctx as *mut u8).sub(ALIGN_TO);
let bytes = (ptr as *mut usize).read();
@ -629,8 +628,8 @@ pub unsafe extern "C" fn rustsecp256k1_v0_5_0_context_destroy(ctx: *mut Context)
alloc::dealloc(ptr, layout);
}
#[cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))))]
#[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))))]
pub unsafe fn secp256k1_context_destroy(ctx: *mut Context) {
rustsecp256k1_v0_5_0_context_destroy(ctx)
}

View File

@ -69,14 +69,14 @@ macro_rules! impl_array_newtype {
impl PartialOrd for $thing {
#[inline]
fn partial_cmp(&self, other: &$thing) -> Option<::core::cmp::Ordering> {
fn partial_cmp(&self, other: &$thing) -> Option<core::cmp::Ordering> {
self[..].partial_cmp(&other[..])
}
}
impl Ord for $thing {
#[inline]
fn cmp(&self, other: &$thing) -> ::core::cmp::Ordering {
fn cmp(&self, other: &$thing) -> core::cmp::Ordering {
self[..].cmp(&other[..])
}
}
@ -89,7 +89,7 @@ macro_rules! impl_array_newtype {
}
}
impl ::core::ops::Index<usize> for $thing {
impl core::ops::Index<usize> for $thing {
type Output = $ty;
#[inline]
@ -99,41 +99,41 @@ macro_rules! impl_array_newtype {
}
}
impl ::core::ops::Index<::core::ops::Range<usize>> for $thing {
impl core::ops::Index<core::ops::Range<usize>> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, index: ::core::ops::Range<usize>) -> &[$ty] {
fn index(&self, index: core::ops::Range<usize>) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[index]
}
}
impl ::core::ops::Index<::core::ops::RangeTo<usize>> for $thing {
impl core::ops::Index<core::ops::RangeTo<usize>> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, index: ::core::ops::RangeTo<usize>) -> &[$ty] {
fn index(&self, index: core::ops::RangeTo<usize>) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[index]
}
}
impl ::core::ops::Index<::core::ops::RangeFrom<usize>> for $thing {
impl core::ops::Index<core::ops::RangeFrom<usize>> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, index: ::core::ops::RangeFrom<usize>) -> &[$ty] {
fn index(&self, index: core::ops::RangeFrom<usize>) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[index]
}
}
impl ::core::ops::Index<::core::ops::RangeFull> for $thing {
impl core::ops::Index<core::ops::RangeFull> for $thing {
type Output = [$ty];
#[inline]
fn index(&self, _: ::core::ops::RangeFull) -> &[$ty] {
fn index(&self, _: core::ops::RangeFull) -> &[$ty] {
let &$thing(ref dat) = self;
&dat[..]
}
@ -142,7 +142,7 @@ macro_rules! impl_array_newtype {
type Target = $ty;
fn as_c_ptr(&self) -> *const Self::Target {
if self.is_empty() {
::core::ptr::null()
core::ptr::null()
} else {
self.as_ptr()
}
@ -150,7 +150,7 @@ macro_rules! impl_array_newtype {
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
if self.is_empty() {
::core::ptr::null::<Self::Target>() as *mut _
core::ptr::null::<Self::Target>() as *mut _
} else {
self.as_mut_ptr()
}
@ -162,8 +162,8 @@ macro_rules! impl_array_newtype {
#[macro_export]
macro_rules! impl_raw_debug {
($thing:ident) => {
impl ::core::fmt::Debug for $thing {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
impl core::fmt::Debug for $thing {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
for i in self[..].iter().cloned() {
write!(f, "{:02x}", i)?;
}

View File

@ -15,9 +15,9 @@
//! # FFI of the recovery module
use ::types::*;
use ::core::fmt;
use {Context, Signature, NonceFn, PublicKey, CPtr};
use crate::{Context, Signature, NonceFn, PublicKey, CPtr, impl_array_newtype};
use crate::types::*;
use core::fmt;
/// Library-internal representation of a Secp256k1 signature + recovery ID
#[repr(C)]
@ -98,13 +98,10 @@ extern "C" {
#[cfg(fuzzing)]
mod fuzz_dummy {
use super::*;
use std::slice;
use core::slice;
use secp256k1_ec_pubkey_create;
use secp256k1_ec_pubkey_parse;
use secp256k1_ec_pubkey_serialize;
use SECP256K1_SER_COMPRESSED;
use crate::{secp256k1_ec_pubkey_create, secp256k1_ec_pubkey_parse, secp256k1_ec_pubkey_serialize, SECP256K1_SER_COMPRESSED};
use super::*;
/// Sets sig to msg32||full pk
pub unsafe fn secp256k1_ecdsa_sign_recoverable(
@ -170,6 +167,6 @@ mod fuzz_dummy {
1
}
}
#[cfg(fuzzing)]
pub use self::fuzz_dummy::*;

View File

@ -1,5 +1,4 @@
#![allow(non_camel_case_types)]
use core::fmt;
pub type c_int = i32;
pub type c_uchar = u8;
@ -10,23 +9,7 @@ pub type size_t = usize;
/// The way we use it makes it fine either way but this type shouldn't be used outside of the library.
pub type c_char = i8;
/// This is an exact copy of <https://doc.rust-lang.org/core/ffi/enum.c_void.html>
/// It should be Equivalent to C's void type when used as a pointer.
///
/// We can replace this with `core::ffi::c_void` once we update the rustc version to >=1.30.0.
#[repr(u8)]
pub enum c_void {
#[doc(hidden)]
__variant1,
#[doc(hidden)]
__variant2,
}
impl fmt::Debug for c_void {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("c_void")
}
}
pub use core::ffi::c_void;
/// A type that is as aligned as the biggest alignment for fundamental types in C
/// since C11 that means as aligned as `max_align_t` is.
@ -45,8 +28,8 @@ impl AlignedType {
pub const ZERO: AlignedType = AlignedType([0u8; 16]);
}
#[cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))]
pub(crate) const ALIGN_TO: usize = ::core::mem::align_of::<AlignedType>();
#[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))]
pub(crate) const ALIGN_TO: usize = core::mem::align_of::<AlignedType>();
#[cfg(test)]
mod tests {
@ -54,7 +37,7 @@ mod tests {
use std::any::TypeId;
use std::mem;
use std::os::raw;
use {types, AlignedType};
use crate::{types, AlignedType};
#[test]
fn verify_types() {

View File

@ -1,24 +1,23 @@
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use ffi::{self, CPtr, types::AlignedType};
use ffi::types::{c_uint, c_void};
use Error;
use Secp256k1;
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
use crate::{Error, Secp256k1};
use crate::ffi::{self, CPtr, types::AlignedType};
use crate::ffi::types::{c_uint, c_void};
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub use self::alloc_only::*;
#[cfg(all(feature = "global-context", feature = "std"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "std"))))]
/// Module implementing a singleton pattern for a global `Secp256k1` context.
pub mod global {
#[cfg(feature = "rand-std")]
use rand;
use std::ops::Deref;
use std::sync::Once;
use {Secp256k1, All};
use crate::{All, Secp256k1};
/// Proxy struct for global `SECP256K1` context.
#[derive(Debug, Copy, Clone)]
@ -104,13 +103,16 @@ mod private {
impl<'buf> Sealed for SignOnlyPreallocated<'buf> {}
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))]
mod alloc_only {
#[cfg(feature = "std")]
use std::alloc;
#[cfg(not(feature = "std"))]
use alloc::alloc;
use crate::alloc::alloc;
use core::marker::PhantomData;
use super::private;
use crate::ffi::{self, types::{c_uint, c_void}};
use crate::{Secp256k1, Signing, Verification, Context, AlignedType};
#[cfg(feature = "rand-std")]
use rand;
@ -119,8 +121,7 @@ mod alloc_only {
impl private::Sealed for All {}
impl private::Sealed for VerifyOnly {}
use super::*;
const ALIGN_TO: usize = ::core::mem::align_of::<AlignedType>();
const ALIGN_TO: usize = core::mem::align_of::<AlignedType>();
/// Represents the set of capabilities needed for signing.
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]

View File

@ -15,14 +15,11 @@
//! Support for shared secret computations.
//!
use core::{ptr, str};
use core::borrow::Borrow;
use core::{borrow::Borrow, ptr, str};
use {Error, from_hex};
use key::{SecretKey, PublicKey};
use ffi::{self, CPtr};
use secp256k1_sys::types::{c_int, c_uchar, c_void};
use constants;
use crate::{constants, Error, ffi::{self, CPtr}, key::{PublicKey, SecretKey}};
// The logic for displaying shared secrets relies on this (see `secret.rs`).
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
@ -97,7 +94,7 @@ impl str::FromStr for SharedSecret {
type Err = Error;
fn from_str(s: &str) -> Result<SharedSecret, Error> {
let mut res = [0u8; SHARED_SECRET_SIZE];
match from_hex(s, &mut res) {
match crate::from_hex(s, &mut res) {
Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)),
_ => Err(Error::InvalidSharedSecret)
}
@ -177,7 +174,7 @@ impl ::serde::Serialize for SharedSecret {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
let mut buf = [0u8; SHARED_SECRET_SIZE * 2];
s.serialize_str(::to_hex(&self.0, &mut buf).expect("fixed-size hex serialization"))
s.serialize_str(crate::to_hex(&self.0, &mut buf).expect("fixed-size hex serialization"))
} else {
s.serialize_bytes(&self.as_ref()[..])
}
@ -204,13 +201,13 @@ impl<'de> ::serde::Deserialize<'de> for SharedSecret {
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
use super::*;
use rand::thread_rng;
use super::super::Secp256k1;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;
use crate::Secp256k1;
use super::SharedSecret;
#[test]
#[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))]
fn ecdh() {
@ -230,7 +227,7 @@ mod tests {
let x = [5u8; 32];
let y = [7u8; 32];
let mut output = [0u8; 64];
let res = unsafe { super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), ptr::null_mut()) };
let res = unsafe { super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), core::ptr::null_mut()) };
assert_eq!(res, 1);
let mut new_x = [0u8; 32];
let mut new_y = [0u8; 32];
@ -244,7 +241,8 @@ mod tests {
#[cfg(not(fuzzing))]
#[cfg(all(feature="rand-std", feature = "std", feature = "bitcoin_hashes"))]
fn bitcoin_hashes_and_sys_generate_same_secret() {
use hashes::{sha256, Hash, HashEngine};
use bitcoin_hashes::{sha256, Hash, HashEngine};
use crate::ecdh::shared_secret_point;
let s = Secp256k1::signing_only();
let (sk1, _) = s.generate_keypair(&mut thread_rng());
@ -292,11 +290,13 @@ mod tests {
#[cfg(all(test, feature = "unstable"))]
mod benches {
use rand::thread_rng;
use test::{Bencher, black_box};
use rand::thread_rng;
use crate::Secp256k1;
use super::SharedSecret;
use super::super::Secp256k1;
#[bench]
pub fn bench_ecdh(bh: &mut Bencher) {

View File

@ -2,8 +2,8 @@
use core::{fmt, str, ops, ptr, mem};
use {Signing, Verification, Message, PublicKey, Secp256k1, SecretKey, from_hex, Error, ffi};
use ffi::CPtr;
use crate::{Signing, Verification, Message, PublicKey, Secp256k1, SecretKey, from_hex, Error, ffi};
use crate::ffi::CPtr;
#[cfg(feature = "recovery")]
mod recovery;
@ -13,7 +13,7 @@ mod recovery;
pub use self::recovery::{RecoveryId, RecoverableSignature};
#[cfg(feature = "global-context")]
use SECP256K1;
use crate::SECP256K1;
/// An ECDSA signature
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
@ -120,7 +120,7 @@ impl SerializedSignature {
/// Convert the serialized signature into the Signature struct.
/// (This DER deserializes it)
pub fn to_signature(&self) -> Result<Signature, Error> {
Signature::from_der(&self)
Signature::from_der(self)
}
/// Create a SerializedSignature from a Signature.
@ -304,8 +304,8 @@ impl From<ffi::Signature> for Signature {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for Signature {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
impl serde::Serialize for Signature {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
s.collect_str(self)
} else {
@ -316,14 +316,14 @@ impl ::serde::Serialize for Signature {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for Signature {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
impl<'de> serde::Deserialize<'de> for Signature {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(::serde_util::FromStrVisitor::new(
d.deserialize_str(crate::serde_util::FromStrVisitor::new(
"a hex string representing a DER encoded Signature"
))
} else {
d.deserialize_bytes(::serde_util::BytesVisitor::new(
d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
"raw byte stream, that represents a DER encoded Signature",
Signature::from_der
))
@ -467,12 +467,11 @@ impl<C: Verification> Secp256k1<C> {
///
/// ```rust
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
/// # use secp256k1::rand::rngs::OsRng;
/// # use secp256k1::rand::thread_rng;
/// # use secp256k1::{Secp256k1, Message, Error};
/// #
/// # let secp = Secp256k1::new();
/// # let mut rng = OsRng::new().expect("OsRng");
/// # let (secret_key, public_key) = secp.generate_keypair(&mut rng);
/// # let (secret_key, public_key) = secp.generate_keypair(&mut thread_rng());
/// #
/// let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
/// let sig = secp.sign(&message, &secret_key);
@ -496,12 +495,11 @@ impl<C: Verification> Secp256k1<C> {
///
/// ```rust
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
/// # use secp256k1::rand::rngs::OsRng;
/// # use secp256k1::rand::thread_rng;
/// # use secp256k1::{Secp256k1, Message, Error};
/// #
/// # let secp = Secp256k1::new();
/// # let mut rng = OsRng::new().expect("OsRng");
/// # let (secret_key, public_key) = secp.generate_keypair(&mut rng);
/// # let (secret_key, public_key) = secp.generate_keypair(&mut thread_rng());
/// #
/// let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
/// let sig = secp.sign_ecdsa(&message, &secret_key);

View File

@ -18,12 +18,10 @@
//!
use core::ptr;
use key;
use crate::{key, Secp256k1, Message, Error, Verification, Signing, ecdsa::Signature};
use super::ffi as super_ffi;
use self::super_ffi::CPtr;
use ffi::recovery as ffi;
use super::*;
use {Verification, Secp256k1, Signing, Message};
use crate::ffi::recovery as ffi;
/// A tag used for recovering the public key from a compact signature.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -38,7 +36,7 @@ impl RecoveryId {
/// Allows library users to create valid recovery IDs from i32.
pub fn from_i32(id: i32) -> Result<RecoveryId, Error> {
match id {
0 | 1 | 2 | 3 => Ok(RecoveryId(id)),
0..=3 => Ok(RecoveryId(id)),
_ => Err(Error::InvalidRecoveryId)
}
}
@ -127,7 +125,7 @@ impl RecoverableSignature {
#[cfg(feature = "global-context")]
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
pub fn recover(&self, msg: &Message) -> Result<key::PublicKey, Error> {
SECP256K1.recover_ecdsa(msg, self)
crate::SECP256K1.recover_ecdsa(msg, self)
}
}
@ -235,9 +233,10 @@ impl<C: Verification> Secp256k1<C> {
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
use super::*;
use rand::{RngCore, thread_rng};
use key::SecretKey;
use crate::{Error, SecretKey, Secp256k1, Message};
use super::{RecoveryId, RecoverableSignature};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

View File

@ -16,22 +16,19 @@
//! Public and secret keys.
//!
#[cfg(any(test, feature = "rand"))] use rand::Rng;
use core::{fmt, ptr, str};
use core::ops::BitXor;
use core::convert::TryFrom;
use super::{from_hex, Secp256k1};
use super::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey};
use ::{Signing};
use Verification;
use constants;
use ffi::{self, CPtr};
use crate::{constants, from_hex, Secp256k1, Signing, Verification};
use crate::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey};
use crate::ffi::{self, CPtr, impl_array_newtype};
use crate::ffi::types::c_uint;
#[cfg(feature = "global-context")]
use {Message, ecdsa, SECP256K1};
use crate::{Message, ecdsa, SECP256K1};
#[cfg(all(feature = "global-context", feature = "rand-std"))]
use schnorr;
use crate::schnorr;
/// Secret 256-bit key used as `x` in an ECDSA signature.
///
@ -122,7 +119,7 @@ impl str::FromStr for PublicKey {
}
#[cfg(any(test, feature = "rand"))]
fn random_32_bytes<R: Rng + ?Sized>(rng: &mut R) -> [u8; 32] {
fn random_32_bytes<R: rand::Rng + ?Sized>(rng: &mut R) -> [u8; 32] {
let mut ret = [0u8; 32];
rng.fill_bytes(&mut ret);
ret
@ -142,7 +139,7 @@ impl SecretKey {
#[inline]
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn new<R: Rng + ?Sized>(rng: &mut R) -> SecretKey {
pub fn new<R: rand::Rng + ?Sized>(rng: &mut R) -> SecretKey {
let mut data = random_32_bytes(rng);
unsafe {
while ffi::secp256k1_ec_seckey_verify(
@ -166,9 +163,8 @@ impl SecretKey {
/// ```
#[inline]
pub fn from_slice(data: &[u8])-> Result<SecretKey, Error> {
match data.len() {
constants::SECRET_KEY_SIZE => {
let mut ret = [0u8; constants::SECRET_KEY_SIZE];
match <[u8; constants::SECRET_KEY_SIZE]>::try_from(data) {
Ok(data) => {
unsafe {
if ffi::secp256k1_ec_seckey_verify(
ffi::secp256k1_context_no_precomp,
@ -178,10 +174,9 @@ impl SecretKey {
return Err(InvalidSecretKey);
}
}
ret[..].copy_from_slice(data);
Ok(SecretKey(ret))
Ok(SecretKey(data))
}
_ => Err(InvalidSecretKey)
Err(_) => Err(InvalidSecretKey)
}
}
@ -321,11 +316,11 @@ impl SecretKey {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for SecretKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
impl serde::Serialize for SecretKey {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
let mut buf = [0u8; constants::SECRET_KEY_SIZE * 2];
s.serialize_str(::to_hex(&self.0, &mut buf).expect("fixed-size hex serialization"))
s.serialize_str(crate::to_hex(&self.0, &mut buf).expect("fixed-size hex serialization"))
} else {
s.serialize_bytes(&self[..])
}
@ -334,8 +329,8 @@ impl ::serde::Serialize for SecretKey {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for SecretKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
impl<'de> serde::Deserialize<'de> for SecretKey {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new(
"a hex string representing 32 byte SecretKey"
@ -462,40 +457,33 @@ impl PublicKey {
/// represented by only a single bit, as x determines it up to one bit.
pub fn serialize(&self) -> [u8; constants::PUBLIC_KEY_SIZE] {
let mut ret = [0u8; constants::PUBLIC_KEY_SIZE];
unsafe {
let mut ret_len = constants::PUBLIC_KEY_SIZE as usize;
let err = ffi::secp256k1_ec_pubkey_serialize(
ffi::secp256k1_context_no_precomp,
ret.as_mut_c_ptr(),
&mut ret_len,
self.as_c_ptr(),
ffi::SECP256K1_SER_COMPRESSED,
);
debug_assert_eq!(err, 1);
debug_assert_eq!(ret_len, ret.len());
}
self.serialize_internal(&mut ret, ffi::SECP256K1_SER_COMPRESSED);
ret
}
#[inline]
/// Serializes the key as a byte-encoded pair of values, in uncompressed form.
pub fn serialize_uncompressed(&self) -> [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] {
let mut ret = [0u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
self.serialize_internal(&mut ret, ffi::SECP256K1_SER_UNCOMPRESSED);
ret
}
unsafe {
let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as usize;
let err = ffi::secp256k1_ec_pubkey_serialize(
#[inline(always)]
fn serialize_internal(&self, ret: &mut [u8], flag: c_uint) {
let mut ret_len = ret.len();
let res = unsafe {
ffi::secp256k1_ec_pubkey_serialize(
ffi::secp256k1_context_no_precomp,
ret.as_mut_c_ptr(),
&mut ret_len,
self.as_c_ptr(),
ffi::SECP256K1_SER_UNCOMPRESSED,
);
debug_assert_eq!(err, 1);
flag,
)
};
debug_assert_eq!(res, 1);
debug_assert_eq!(ret_len, ret.len());
}
ret
}
#[inline]
/// Negates the public key in place.
@ -671,8 +659,8 @@ impl From<ffi::PublicKey> for PublicKey {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for PublicKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
impl serde::Serialize for PublicKey {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
s.collect_str(self)
} else {
@ -683,8 +671,8 @@ impl ::serde::Serialize for PublicKey {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for PublicKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
impl<'de> serde::Deserialize<'de> for PublicKey {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new(
"an ASCII hex string representing a public key"
@ -699,13 +687,13 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey {
}
impl PartialOrd for PublicKey {
fn partial_cmp(&self, other: &PublicKey) -> Option<::core::cmp::Ordering> {
fn partial_cmp(&self, other: &PublicKey) -> Option<core::cmp::Ordering> {
self.serialize().partial_cmp(&other.serialize())
}
}
impl Ord for PublicKey {
fn cmp(&self, other: &PublicKey) -> ::core::cmp::Ordering {
fn cmp(&self, other: &PublicKey) -> core::cmp::Ordering {
self.serialize().cmp(&other.serialize())
}
}
@ -837,7 +825,7 @@ impl KeyPair {
#[inline]
#[cfg(any(test, 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 ret = [0u8; 32];
rng.fill_bytes(&mut ret);
@ -992,11 +980,11 @@ impl str::FromStr for KeyPair {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for KeyPair {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
impl serde::Serialize for KeyPair {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
let mut buf = [0u8; constants::SECRET_KEY_SIZE * 2];
s.serialize_str(::to_hex(&self.secret_bytes(), &mut buf)
s.serialize_str(crate::to_hex(&self.secret_bytes(), &mut buf)
.expect("fixed-size hex serialization"))
} else {
s.serialize_bytes(&self.0[..])
@ -1006,8 +994,8 @@ impl ::serde::Serialize for KeyPair {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for KeyPair {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
impl<'de> serde::Deserialize<'de> for KeyPair {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new(
"a hex string representing 32 byte KeyPair"
@ -1360,7 +1348,7 @@ impl fmt::Display for InvalidParityValue {
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for InvalidParityValue {}
impl std::error::Error for InvalidParityValue {}
impl From<InvalidParityValue> for Error {
fn from(error: InvalidParityValue) -> Self {
@ -1371,8 +1359,8 @@ impl From<InvalidParityValue> for Error {
/// The parity is serialized as `u8` - `0` for even, `1` for odd.
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for Parity {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
impl serde::Serialize for Parity {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_u8(self.to_u8())
}
}
@ -1380,11 +1368,11 @@ impl ::serde::Serialize for Parity {
/// The parity is deserialized as `u8` - `0` for even, `1` for odd.
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for Parity {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
impl<'de> serde::Deserialize<'de> for Parity {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
struct Visitor;
impl<'de> ::serde::de::Visitor<'de> for Visitor
impl<'de> serde::de::Visitor<'de> for Visitor
{
type Value = Parity;
@ -1393,7 +1381,7 @@ impl<'de> ::serde::Deserialize<'de> for Parity {
}
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
where E: ::serde::de::Error
where E: serde::de::Error
{
use serde::de::Unexpected;
@ -1425,8 +1413,8 @@ impl From<ffi::XOnlyPublicKey> for XOnlyPublicKey {
}
}
impl From<::key::PublicKey> for XOnlyPublicKey {
fn from(src: ::key::PublicKey) -> XOnlyPublicKey {
impl From<PublicKey> for XOnlyPublicKey {
fn from(src: PublicKey) -> XOnlyPublicKey {
unsafe {
let mut pk = ffi::XOnlyPublicKey::new();
assert_eq!(
@ -1445,8 +1433,8 @@ impl From<::key::PublicKey> for XOnlyPublicKey {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for XOnlyPublicKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
impl serde::Serialize for XOnlyPublicKey {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
s.collect_str(self)
} else {
@ -1457,8 +1445,8 @@ impl ::serde::Serialize for XOnlyPublicKey {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for XOnlyPublicKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
impl<'de> serde::Deserialize<'de> for XOnlyPublicKey {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new(
"a hex string representing 32 byte schnorr public key"
@ -1486,8 +1474,7 @@ impl<'de> ::serde::Deserialize<'de> for XOnlyPublicKey {
#[cfg(all(feature = "global-context", feature = "serde"))]
pub mod serde_keypair {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use key::KeyPair;
use key::SecretKey;
use crate::key::{KeyPair, SecretKey};
#[allow(missing_docs)]
pub fn serialize<S>(key: &KeyPair, serializer: S) -> Result<S::Ok, S::Error>
@ -1505,7 +1492,7 @@ pub mod serde_keypair {
let secret_key = SecretKey::deserialize(deserializer)?;
Ok(KeyPair::from_secret_key(
&::SECP256K1,
&crate::SECP256K1,
&secret_key,
))
}
@ -1514,23 +1501,18 @@ pub mod serde_keypair {
#[cfg(test)]
#[allow(unused_imports)]
mod test {
use super::*;
#[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 constants;
use Error::{InvalidPublicKey, InvalidSecretKey};
use rand::{Error, RngCore, thread_rng, rngs::mock::StepRng};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;
use super::{XOnlyPublicKey, PublicKey, Secp256k1, SecretKey, KeyPair, Parity};
use crate::{constants, from_hex, to_hex};
use crate::Error::{InvalidPublicKey, InvalidSecretKey};
macro_rules! hex {
($hex:expr) => ({
let mut result = vec![0; $hex.len() / 2];
@ -1601,7 +1583,6 @@ mod test {
#[test]
#[cfg(any(feature = "alloc", feature = "std"))]
fn test_out_of_range() {
struct BadRng(u8);
impl RngCore for BadRng {
fn next_u32(&mut self) -> u32 { unimplemented!() }
@ -1694,28 +1675,9 @@ 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 {
self.0 = self.0.wrapping_add(1);
self.0
}
fn next_u64(&mut self) -> u64 {
self.next_u32() as u64
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest);
}
fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), Error> {
Err(Error::new(ErrorKind::Unavailable, "not implemented"))
}
}
let s = Secp256k1::new();
let (sk, _) = s.generate_keypair(&mut DumbRng(0));
let (sk, _) = s.generate_keypair(&mut StepRng::new(1, 1));
assert_eq!(&format!("{:?}", sk),
"SecretKey(#d3e0c51a23169bb5)");
@ -1781,7 +1743,7 @@ mod test {
assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err());
assert!(PublicKey::from_str("xx0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err());
let long_str: String = iter::repeat('a').take(1024 * 1024).collect();
let long_str: String = core::iter::repeat('a').take(1024 * 1024).collect();
assert!(SecretKey::from_str(&long_str).is_err());
assert!(PublicKey::from_str(&long_str).is_err());
}
@ -1792,26 +1754,9 @@ mod test {
#[cfg(not(fuzzing))]
#[cfg(any(feature = "alloc", feature = "std"))]
fn test_pubkey_serialize() {
struct DumbRng(u32);
impl RngCore for DumbRng {
fn next_u32(&mut self) -> u32 {
self.0 = self.0.wrapping_add(1);
self.0
}
fn next_u64(&mut self) -> u64 {
self.next_u32() as u64
}
fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), Error> {
Err(Error::new(ErrorKind::Unavailable, "not implemented"))
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest);
}
}
let s = Secp256k1::new();
let (_, pk1) = s.generate_keypair(&mut DumbRng(0));
let (_, pk1) = s.generate_keypair(&mut StepRng::new(1,1));
assert_eq!(&pk1.serialize_uncompressed()[..],
&[4, 124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9, 181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229, 185, 28, 165, 110, 27, 3, 162, 126, 238, 167, 157, 242, 221, 76, 251, 237, 34, 231, 72, 39, 245, 3, 191, 64, 111, 170, 117, 103, 82, 28, 102, 163][..]);
assert_eq!(&pk1.serialize()[..],
@ -2095,7 +2040,7 @@ mod test {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_test::{Configure, Token, assert_tokens};
use super::serde_keypair;
use key::KeyPair;
use crate::key::KeyPair;
// Normally users would derive the serde traits, but we can't easily enable the serde macros
// here, so they are implemented manually to be able to test the behaviour.
@ -2125,7 +2070,7 @@ mod test {
01010101010101010001020304050607ffff0000ffff00006363636363636363\
";
let sk = KeyPairWrapper(KeyPair::from_seckey_slice(&::SECP256K1, &SK_BYTES).unwrap());
let sk = KeyPairWrapper(KeyPair::from_seckey_slice(&crate::SECP256K1, &SK_BYTES).unwrap());
assert_tokens(&sk.compact(), &[Token::BorrowedBytes(&SK_BYTES[..])]);
assert_tokens(&sk.compact(), &[Token::Bytes(&SK_BYTES)]);

View File

@ -47,8 +47,7 @@
//! use secp256k1::hashes::sha256;
//!
//! let secp = Secp256k1::new();
//! let mut rng = OsRng::new().expect("OsRng");
//! let (secret_key, public_key) = secp.generate_keypair(&mut rng);
//! let (secret_key, public_key) = secp.generate_keypair(&mut OsRng);
//! let message = Message::from_hashed_data::<sha256::Hash>("Hello World!".as_bytes());
//!
//! let sig = secp.sign_ecdsa(&message, &secret_key);
@ -150,47 +149,19 @@
//! * `bitcoin_hashes` - enables interaction with the `bitcoin-hashes` crate (e.g. conversions).
// Coding conventions
#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_docs)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)]
#![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[macro_use]
pub extern crate secp256k1_sys;
pub use secp256k1_sys as ffi;
#[cfg(feature = "bitcoin_hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin_hashes")))]
pub extern crate bitcoin_hashes as hashes;
#[cfg(all(test, feature = "unstable"))]
extern crate test;
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub extern crate rand;
#[cfg(any(test))]
extern crate rand_core;
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate serde_test;
#[cfg(any(test, feature = "rand"))]
use rand::Rng;
#[cfg(any(test, feature = "std"))]
extern crate core;
#[cfg(all(test, target_arch = "wasm32"))]
extern crate wasm_bindgen_test;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(any(test, feature = "std"))]
extern crate core;
#[cfg(all(test, feature = "unstable"))]
extern crate test;
#[macro_use]
mod macros;
@ -206,18 +177,28 @@ pub mod schnorr;
#[cfg(feature = "serde")]
mod serde_util;
pub use key::*;
pub use context::*;
use core::marker::PhantomData;
use core::{mem, fmt, str};
use ffi::{CPtr, types::AlignedType};
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub use rand;
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub use serde;
#[cfg(feature = "bitcoin_hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin_hashes")))]
pub use bitcoin_hashes as hashes;
pub use secp256k1_sys as ffi;
pub use crate::key::{PublicKey, SecretKey};
pub use crate::context::*;
pub use crate::key::*;
#[cfg(feature = "global-context")]
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
pub use context::global::SECP256K1;
use core::{fmt, str, mem, marker::PhantomData};
use crate::ffi::{CPtr, impl_array_newtype, types::AlignedType};
#[cfg(feature = "bitcoin_hashes")]
use hashes::Hash;
use crate::hashes::Hash;
// Backwards compatible changes
/// Schnorr Signature related methods.
@ -225,13 +206,13 @@ use hashes::Hash;
pub mod schnorrsig {
#[deprecated(since = "0.21.0", note = "Use crate::XOnlyPublicKey instead.")]
/// backwards compatible re-export of xonly key
pub type PublicKey = super::XOnlyPublicKey;
pub type PublicKey = crate::key::XOnlyPublicKey;
/// backwards compatible re-export of keypair
#[deprecated(since = "0.21.0", note = "Use crate::KeyPair instead.")]
pub type KeyPair = super::KeyPair;
pub type KeyPair = crate::key::KeyPair;
/// backwards compatible re-export of schnorr signatures
#[deprecated(since = "0.21.0", note = "Use schnorr::Signature instead.")]
pub type Signature = super::schnorr::Signature;
pub type Signature = crate::schnorr::Signature;
}
#[deprecated(since = "0.21.0", note = "Use ecdsa::Signature instead.")]
@ -470,7 +451,7 @@ impl<C: Context> Secp256k1<C> {
/// [libsecp256k1](https://github.com/bitcoin-core/secp256k1/commit/d2275795ff22a6f4738869f5528fbbb61738aa48).
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn randomize<R: Rng + ?Sized>(&mut self, rng: &mut R) {
pub fn randomize<R: rand::Rng + ?Sized>(&mut self, rng: &mut R) {
let mut seed = [0u8; 32];
rng.fill_bytes(&mut seed);
self.seeded_randomize(&seed);
@ -501,7 +482,7 @@ impl<C: Signing> Secp256k1<C> {
#[inline]
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn generate_keypair<R: Rng + ?Sized>(&self, rng: &mut R)
pub fn generate_keypair<R: rand::Rng + ?Sized>(&self, rng: &mut R)
-> (key::SecretKey, key::PublicKey) {
let sk = key::SecretKey::new(rng);
let pk = key::PublicKey::from_secret_key(self, &sk);
@ -513,7 +494,7 @@ impl<C: Signing> Secp256k1<C> {
#[inline]
#[cfg(all(feature = "global-context", feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "rand"))))]
pub fn generate_keypair<R: Rng + ?Sized>(rng: &mut R) -> (key::SecretKey, key::PublicKey) {
pub fn generate_keypair<R: rand::Rng + ?Sized>(rng: &mut R) -> (key::SecretKey, key::PublicKey) {
SECP256K1.generate_keypair(rng)
}
@ -569,14 +550,18 @@ fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
#[cfg(test)]
mod tests {
use super::*;
use std::marker::PhantomData;
use std::str::FromStr;
use rand::{RngCore, thread_rng};
use core::str::FromStr;
use ffi::types::AlignedType;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;
use crate::{constants, ecdsa, from_hex, to_hex, Message, PublicKey, Secp256k1, SecretKey, Error};
use crate::context::*;
use crate::ffi::{self, types::AlignedType};
macro_rules! hex {
($hex:expr) => ({
let mut result = vec![0; $hex.len() / 2];
@ -1038,6 +1023,7 @@ mod tests {
#[cfg(feature = "global-context")]
#[test]
fn test_global_context() {
use crate::SECP256K1;
let sk_data = hex!("e6dd32f8761625f105c39a39f19370b3521d845a12456d60ce44debd0a362641");
let sk = SecretKey::from_slice(&sk_data).unwrap();
let msg_data = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
@ -1054,8 +1040,7 @@ mod tests {
#[cfg(feature = "bitcoin_hashes")]
#[test]
fn test_from_hash() {
use hashes;
use hashes::Hash;
use crate::hashes::{self, Hash};
let test_bytes = "Hello world!".as_bytes();
@ -1079,40 +1064,19 @@ mod tests {
#[cfg(all(test, feature = "unstable"))]
mod benches {
use rand::{thread_rng, RngCore};
use test::{Bencher, black_box};
use super::{Secp256k1, Message};
use rand::{RngCore, thread_rng};
use rand::rngs::mock::StepRng;
use super::{Message, Secp256k1};
#[bench]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn generate(bh: &mut Bencher) {
struct CounterRng(u64);
impl RngCore for CounterRng {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
fn next_u64(&mut self) -> u64 {
self.0 += 1;
self.0
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
for chunk in dest.chunks_mut(64/8) {
let rand: [u8; 64/8] = unsafe {std::mem::transmute(self.next_u64())};
chunk.copy_from_slice(&rand[..chunk.len()]);
}
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
Ok(self.fill_bytes(dest))
}
}
let s = Secp256k1::new();
let mut r = CounterRng(0);
let mut r = StepRng::new(1, 1);
bh.iter( || {
let (sk, pk) = s.generate_keypair(&mut r);
black_box(sk);

View File

@ -15,8 +15,8 @@
macro_rules! impl_pretty_debug {
($thing:ident) => {
impl ::core::fmt::Debug for $thing {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
impl core::fmt::Debug for $thing {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}(", stringify!($thing))?;
for i in &self[..] {
write!(f, "{:02x}", i)?;

View File

@ -2,19 +2,17 @@
//! Support for Schnorr signatures.
//!
#[cfg(any(test, feature = "rand-std"))]
use rand::thread_rng;
use core::{fmt, ptr, str};
#[cfg(any(test, feature = "rand"))]
use rand::{CryptoRng, Rng};
use super::{from_hex, Error};
use core::{fmt, ptr, str};
use ffi::{self, CPtr};
use {constants, Secp256k1};
use {Message, Signing, Verification, KeyPair, XOnlyPublicKey};
use crate::{constants, Error, from_hex, Message, Secp256k1, Signing, Verification};
use crate::key::{KeyPair, XOnlyPublicKey};
use crate::ffi::{self, CPtr, impl_array_newtype};
#[cfg(all(feature = "global-context", feature = "rand-std"))]
use SECP256K1;
use crate::SECP256K1;
/// Represents a Schnorr signature.
pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
@ -22,9 +20,8 @@ impl_array_newtype!(Signature, u8, constants::SCHNORR_SIGNATURE_SIZE);
impl_pretty_debug!(Signature);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for Signature {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
impl serde::Serialize for Signature {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
s.collect_str(self)
} else {
@ -34,9 +31,8 @@ impl ::serde::Serialize for Signature {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for Signature {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
impl<'de> serde::Deserialize<'de> for Signature {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new(
"a hex string representing 64 byte schnorr signature"
@ -139,8 +135,7 @@ impl<C: Signing> Secp256k1<C> {
#[cfg(any(test, feature = "rand-std"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
pub fn sign_schnorr(&self, msg: &Message, keypair: &KeyPair) -> Signature {
let mut rng = thread_rng();
self.sign_schnorr_with_rng(msg, keypair, &mut rng)
self.sign_schnorr_with_rng(msg, keypair, &mut rand::thread_rng())
}
/// Create a schnorr signature without using any auxiliary random data.
@ -276,21 +271,16 @@ impl <C: Signing> Secp256k1<C> {
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
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;
use core::str::FromStr;
use rand::{RngCore, rngs::ThreadRng, thread_rng};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
use crate::schnorr::{KeyPair, XOnlyPublicKey, Signature};
use crate::Error::InvalidPublicKey;
use super::*;
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
@ -338,7 +328,7 @@ mod tests {
#[cfg(all(feature = "std", feature = "rand-std"))]
fn sign_helper(
sign: fn(&Secp256k1<All>, &Message, &KeyPair, &mut ThreadRng) -> Signature,
sign: fn(&Secp256k1<crate::All>, &Message, &KeyPair, &mut ThreadRng) -> Signature,
) {
let secp = Secp256k1::new();
@ -429,8 +419,8 @@ mod tests {
let keypair = KeyPair::from_seckey_str(&secp, sk_str).unwrap();
let sk = SecretKey::from_keypair(&keypair);
assert_eq!(SecretKey::from_str(sk_str).unwrap(), sk);
let pk = ::key::PublicKey::from_keypair(&keypair);
assert_eq!(::key::PublicKey::from_secret_key(&secp, &sk), pk);
let pk = crate::key::PublicKey::from_keypair(&keypair);
assert_eq!(crate::key::PublicKey::from_secret_key(&secp, &sk), pk);
let (xpk, _parity) = keypair.x_only_public_key();
assert_eq!(XOnlyPublicKey::from(pk), xpk);
}
@ -515,7 +505,7 @@ mod tests {
)
.is_err());
let long_str: String = iter::repeat('a').take(1024 * 1024).collect();
let long_str: String = core::iter::repeat('a').take(1024 * 1024).collect();
assert!(XOnlyPublicKey::from_str(&long_str).is_err());
}
@ -525,26 +515,9 @@ mod tests {
#[cfg(not(fuzzing))]
#[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))]
fn test_pubkey_serialize() {
struct DumbRng(u32);
impl RngCore for DumbRng {
fn next_u32(&mut self) -> u32 {
self.0 = self.0.wrapping_add(1);
self.0
}
fn next_u64(&mut self) -> u64 {
self.next_u32() as u64
}
fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), Error> {
Err(Error::new(ErrorKind::Unavailable, "not implemented"))
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest);
}
}
use rand::rngs::mock::StepRng;
let secp = Secp256k1::new();
let kp = KeyPair::new(&secp, &mut DumbRng(0));
let kp = KeyPair::new(&secp, &mut StepRng::new(1, 1));
let (pk, _parity) = kp.x_only_public_key();
assert_eq!(
&pk.serialize()[..],

View File

@ -14,25 +14,23 @@
//! Helpers for displaying secret values
use ::core::fmt;
use ::{SecretKey, KeyPair, to_hex};
use ecdh::SharedSecret;
use constants::SECRET_KEY_SIZE;
use core::fmt;
use crate::{to_hex, constants::SECRET_KEY_SIZE, key::{SecretKey, KeyPair}, ecdh::SharedSecret};
macro_rules! impl_display_secret {
// Default hasher exists only in standard library and not alloc
($thing:ident) => {
#[cfg(feature = "std")]
impl ::core::fmt::Debug for $thing {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
use ::core::hash::Hasher;
#[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;
const DEBUG_HASH_TAG: &[u8] = &[
0x66, 0xa6, 0x77, 0x1b, 0x9b, 0x6d, 0xae, 0xa1, 0xb2, 0xee, 0x4e, 0x07, 0x49,
0x4a, 0xac, 0x87, 0xa9, 0xb8, 0x5b, 0x4b, 0x35, 0x02, 0xaa, 0x6d, 0x0f, 0x79,
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22
]; // =SHA256(b"rust-secp256k1DEBUG");
let mut hasher = ::std::collections::hash_map::DefaultHasher::new();
let mut hasher = std::collections::hash_map::DefaultHasher::new();
hasher.write(DEBUG_HASH_TAG);
hasher.write(DEBUG_HASH_TAG);
@ -48,7 +46,7 @@ macro_rules! impl_display_secret {
#[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};
use crate::hashes::{sha256, Hash, HashEngine};
let tag = "rust-secp256k1DEBUG";