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: ACK5d2f1ceb64
apoelstra: ACK5d2f1ceb64
Tree-SHA512: 5bf84e7ebb6286d59f8cada0bb712c46336f0dd6c35b67e6f4ba323b5484ad925b99b73e778ae4608f123938e7ee8705a0aec576cd9c065072c4ecf1248e3470
This commit is contained in:
commit
4f7f138797
|
@ -36,7 +36,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
rust: [stable, beta, nightly, 1.29.0]
|
rust: [stable, beta, nightly, 1.41.1]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Crate
|
- name: Checkout Crate
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
@ -46,9 +46,6 @@ jobs:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: ${{ matrix.rust }}
|
toolchain: ${{ matrix.rust }}
|
||||||
override: true
|
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
|
- name: Running cargo
|
||||||
env:
|
env:
|
||||||
DO_FEATURE_MATRIX: true
|
DO_FEATURE_MATRIX: true
|
||||||
|
@ -59,7 +56,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- name: Checkout Crate
|
- name: Checkout Crate
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -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."
|
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" ]
|
keywords = [ "crypto", "ECDSA", "secp256k1", "libsecp256k1", "bitcoin" ]
|
||||||
readme = "README.md"
|
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
|
# Should make docs.rs show all functions, even those behind non-default features
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
@ -20,9 +20,9 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
[features]
|
[features]
|
||||||
unstable = ["recovery", "rand-std"]
|
unstable = ["recovery", "rand-std"]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["secp256k1-sys/std"]
|
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 = []
|
alloc = ["secp256k1-sys/alloc"]
|
||||||
bitcoin-hashes-std = ["bitcoin_hashes/std"]
|
bitcoin-hashes-std = ["bitcoin_hashes/std"]
|
||||||
rand-std = ["rand/std"]
|
rand-std = ["rand/std"]
|
||||||
recovery = ["secp256k1-sys/recovery"]
|
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
|
# 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
|
# the respective -std feature e.g., bitcoin-hashes-std
|
||||||
bitcoin_hashes = { version = "0.10", default-features = false, optional = true }
|
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]
|
[dev-dependencies]
|
||||||
rand = "0.6"
|
rand = "0.8"
|
||||||
rand_core = "0.4"
|
rand_core = "0.6"
|
||||||
serde_test = "1.0"
|
serde_test = "1.0"
|
||||||
bitcoin_hashes = "0.10"
|
bitcoin_hashes = "0.10"
|
||||||
|
|
||||||
[target.wasm32-unknown-unknown.dev-dependencies]
|
[target.wasm32-unknown-unknown.dev-dependencies]
|
||||||
wasm-bindgen-test = "0.3"
|
wasm-bindgen-test = "0.3"
|
||||||
rand = { version = "0.6", features = ["wasm-bindgen"] }
|
getrandom = { version = "0.2", features = ["js"] }
|
||||||
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
|
|
16
README.md
16
README.md
|
@ -20,21 +20,7 @@ Contributions to this library are welcome. A few guidelines:
|
||||||
* Any breaking changes must have an accompanied entry in CHANGELOG.md
|
* Any breaking changes must have an accompanied entry in CHANGELOG.md
|
||||||
* No new dependencies, please.
|
* 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.
|
* 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**.
|
* This library should always compile with any combination of features on **Rust 1.41.1**.
|
||||||
|
|
||||||
## 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
|
|
||||||
```
|
|
||||||
|
|
||||||
## Fuzzing
|
## Fuzzing
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
msrv = "1.29"
|
msrv = "1.41.1"
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
extern crate secp256k1;
|
extern crate secp256k1;
|
||||||
|
|
||||||
use secp256k1::rand::rngs::OsRng;
|
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 = OsRng::new().unwrap();
|
let mut rng = thread_rng();
|
||||||
// First option:
|
// First option:
|
||||||
let (seckey, pubkey) = secp.generate_keypair(&mut rng);
|
let (seckey, pubkey) = secp.generate_keypair(&mut rng);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ keywords = [ "secp256k1", "libsecp256k1", "ffi" ]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
links = "rustsecp256k1_v0_5_0"
|
links = "rustsecp256k1_v0_5_0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
# Should make docs.rs show all functions, even those behind non-default features
|
# Should make docs.rs show all functions, even those behind non-default features
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
@ -29,5 +30,6 @@ libc = "0.2"
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
recovery = []
|
recovery = []
|
||||||
lowmemory = []
|
lowmemory = []
|
||||||
std = []
|
std = ["alloc"]
|
||||||
|
alloc = []
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,7 @@
|
||||||
//! not be needed for most users.
|
//! not be needed for most users.
|
||||||
|
|
||||||
// Coding conventions
|
// Coding conventions
|
||||||
#![deny(non_upper_case_globals)]
|
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case, unused_mut)]
|
||||||
#![deny(non_camel_case_types)]
|
|
||||||
#![deny(non_snake_case)]
|
|
||||||
#![deny(unused_mut)]
|
|
||||||
|
|
||||||
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
@ -28,10 +25,12 @@
|
||||||
#[cfg(any(test, feature = "std"))]
|
#[cfg(any(test, feature = "std"))]
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
#[cfg(fuzzing)]
|
#[cfg(fuzzing)]
|
||||||
const THIS_UNUSED_CONSTANT_IS_YOUR_WARNING_THAT_ALL_THE_CRYPTO_IN_THIS_LIB_IS_DISABLED_FOR_FUZZING: usize = 0;
|
const THIS_UNUSED_CONSTANT_IS_YOUR_WARNING_THAT_ALL_THE_CRYPTO_IN_THIS_LIB_IS_DISABLED_FOR_FUZZING: usize = 0;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
mod macros;
|
mod macros;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
@ -585,11 +584,11 @@ extern "C" {
|
||||||
///
|
///
|
||||||
/// The newly created secp256k1 raw context.
|
/// The newly created secp256k1 raw context.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[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 = "std", 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 {
|
pub unsafe extern "C" fn rustsecp256k1_v0_5_0_context_create(flags: c_uint) -> *mut Context {
|
||||||
use core::mem;
|
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::align_of::<&usize>());
|
assert!(ALIGN_TO >= mem::align_of::<&usize>());
|
||||||
assert!(ALIGN_TO >= mem::size_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)
|
secp256k1_context_preallocated_create(ptr, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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 = "std", 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 {
|
pub unsafe fn secp256k1_context_create(flags: c_uint) -> *mut Context {
|
||||||
rustsecp256k1_v0_5_0_context_create(flags)
|
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()`.
|
/// The pointer shouldn't be used after passing to this function, consider it as passing it to `free()`.
|
||||||
///
|
///
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[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 = "std", 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) {
|
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);
|
secp256k1_context_preallocated_destroy(ctx);
|
||||||
let ptr = (ctx as *mut u8).sub(ALIGN_TO);
|
let ptr = (ctx as *mut u8).sub(ALIGN_TO);
|
||||||
let bytes = (ptr as *mut usize).read();
|
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);
|
alloc::dealloc(ptr, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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 = "std", 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) {
|
pub unsafe fn secp256k1_context_destroy(ctx: *mut Context) {
|
||||||
rustsecp256k1_v0_5_0_context_destroy(ctx)
|
rustsecp256k1_v0_5_0_context_destroy(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,14 +69,14 @@ macro_rules! impl_array_newtype {
|
||||||
|
|
||||||
impl PartialOrd for $thing {
|
impl PartialOrd for $thing {
|
||||||
#[inline]
|
#[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[..])
|
self[..].partial_cmp(&other[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for $thing {
|
impl Ord for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cmp(&self, other: &$thing) -> ::core::cmp::Ordering {
|
fn cmp(&self, other: &$thing) -> core::cmp::Ordering {
|
||||||
self[..].cmp(&other[..])
|
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;
|
type Output = $ty;
|
||||||
|
|
||||||
#[inline]
|
#[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];
|
type Output = [$ty];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: ::core::ops::Range<usize>) -> &[$ty] {
|
fn index(&self, index: core::ops::Range<usize>) -> &[$ty] {
|
||||||
let &$thing(ref dat) = self;
|
let &$thing(ref dat) = self;
|
||||||
&dat[index]
|
&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];
|
type Output = [$ty];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: ::core::ops::RangeTo<usize>) -> &[$ty] {
|
fn index(&self, index: core::ops::RangeTo<usize>) -> &[$ty] {
|
||||||
let &$thing(ref dat) = self;
|
let &$thing(ref dat) = self;
|
||||||
&dat[index]
|
&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];
|
type Output = [$ty];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: ::core::ops::RangeFrom<usize>) -> &[$ty] {
|
fn index(&self, index: core::ops::RangeFrom<usize>) -> &[$ty] {
|
||||||
let &$thing(ref dat) = self;
|
let &$thing(ref dat) = self;
|
||||||
&dat[index]
|
&dat[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::core::ops::Index<::core::ops::RangeFull> for $thing {
|
impl core::ops::Index<core::ops::RangeFull> for $thing {
|
||||||
type Output = [$ty];
|
type Output = [$ty];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, _: ::core::ops::RangeFull) -> &[$ty] {
|
fn index(&self, _: core::ops::RangeFull) -> &[$ty] {
|
||||||
let &$thing(ref dat) = self;
|
let &$thing(ref dat) = self;
|
||||||
&dat[..]
|
&dat[..]
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ macro_rules! impl_array_newtype {
|
||||||
type Target = $ty;
|
type Target = $ty;
|
||||||
fn as_c_ptr(&self) -> *const Self::Target {
|
fn as_c_ptr(&self) -> *const Self::Target {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
::core::ptr::null()
|
core::ptr::null()
|
||||||
} else {
|
} else {
|
||||||
self.as_ptr()
|
self.as_ptr()
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ macro_rules! impl_array_newtype {
|
||||||
|
|
||||||
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
::core::ptr::null::<Self::Target>() as *mut _
|
core::ptr::null::<Self::Target>() as *mut _
|
||||||
} else {
|
} else {
|
||||||
self.as_mut_ptr()
|
self.as_mut_ptr()
|
||||||
}
|
}
|
||||||
|
@ -162,8 +162,8 @@ macro_rules! impl_array_newtype {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_raw_debug {
|
macro_rules! impl_raw_debug {
|
||||||
($thing:ident) => {
|
($thing:ident) => {
|
||||||
impl ::core::fmt::Debug for $thing {
|
impl core::fmt::Debug for $thing {
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
for i in self[..].iter().cloned() {
|
for i in self[..].iter().cloned() {
|
||||||
write!(f, "{:02x}", i)?;
|
write!(f, "{:02x}", i)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
//! # FFI of the recovery module
|
//! # FFI of the recovery module
|
||||||
|
|
||||||
use ::types::*;
|
use crate::{Context, Signature, NonceFn, PublicKey, CPtr, impl_array_newtype};
|
||||||
use ::core::fmt;
|
use crate::types::*;
|
||||||
use {Context, Signature, NonceFn, PublicKey, CPtr};
|
use core::fmt;
|
||||||
|
|
||||||
/// Library-internal representation of a Secp256k1 signature + recovery ID
|
/// Library-internal representation of a Secp256k1 signature + recovery ID
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -98,13 +98,10 @@ extern "C" {
|
||||||
|
|
||||||
#[cfg(fuzzing)]
|
#[cfg(fuzzing)]
|
||||||
mod fuzz_dummy {
|
mod fuzz_dummy {
|
||||||
use super::*;
|
use core::slice;
|
||||||
use std::slice;
|
|
||||||
|
|
||||||
use secp256k1_ec_pubkey_create;
|
use crate::{secp256k1_ec_pubkey_create, secp256k1_ec_pubkey_parse, secp256k1_ec_pubkey_serialize, SECP256K1_SER_COMPRESSED};
|
||||||
use secp256k1_ec_pubkey_parse;
|
use super::*;
|
||||||
use secp256k1_ec_pubkey_serialize;
|
|
||||||
use SECP256K1_SER_COMPRESSED;
|
|
||||||
|
|
||||||
/// Sets sig to msg32||full pk
|
/// Sets sig to msg32||full pk
|
||||||
pub unsafe fn secp256k1_ecdsa_sign_recoverable(
|
pub unsafe fn secp256k1_ecdsa_sign_recoverable(
|
||||||
|
@ -170,6 +167,6 @@ mod fuzz_dummy {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(fuzzing)]
|
#[cfg(fuzzing)]
|
||||||
pub use self::fuzz_dummy::*;
|
pub use self::fuzz_dummy::*;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
use core::fmt;
|
|
||||||
|
|
||||||
pub type c_int = i32;
|
pub type c_int = i32;
|
||||||
pub type c_uchar = u8;
|
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.
|
/// 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;
|
pub type c_char = i8;
|
||||||
|
|
||||||
/// This is an exact copy of <https://doc.rust-lang.org/core/ffi/enum.c_void.html>
|
pub use core::ffi::c_void;
|
||||||
/// 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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type that is as aligned as the biggest alignment for fundamental types in C
|
/// 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.
|
/// since C11 that means as aligned as `max_align_t` is.
|
||||||
|
@ -45,8 +28,8 @@ impl AlignedType {
|
||||||
pub const ZERO: AlignedType = AlignedType([0u8; 16]);
|
pub const ZERO: AlignedType = AlignedType([0u8; 16]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(rust_secp_no_symbol_renaming)))]
|
#[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))]
|
||||||
pub(crate) const ALIGN_TO: usize = ::core::mem::align_of::<AlignedType>();
|
pub(crate) const ALIGN_TO: usize = core::mem::align_of::<AlignedType>();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -54,7 +37,7 @@ mod tests {
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw;
|
use std::os::raw;
|
||||||
use {types, AlignedType};
|
use crate::{types, AlignedType};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_types() {
|
fn verify_types() {
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem::ManuallyDrop;
|
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"))]
|
use crate::{Error, Secp256k1};
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
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::*;
|
pub use self::alloc_only::*;
|
||||||
|
|
||||||
#[cfg(all(feature = "global-context", feature = "std"))]
|
#[cfg(all(feature = "global-context", feature = "std"))]
|
||||||
#[cfg_attr(docsrs, doc(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.
|
/// Module implementing a singleton pattern for a global `Secp256k1` context.
|
||||||
pub mod global {
|
pub mod global {
|
||||||
#[cfg(feature = "rand-std")]
|
|
||||||
use rand;
|
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
use {Secp256k1, All};
|
|
||||||
|
use crate::{All, Secp256k1};
|
||||||
|
|
||||||
/// Proxy struct for global `SECP256K1` context.
|
/// Proxy struct for global `SECP256K1` context.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -104,13 +103,16 @@ mod private {
|
||||||
impl<'buf> Sealed for SignOnlyPreallocated<'buf> {}
|
impl<'buf> Sealed for SignOnlyPreallocated<'buf> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(feature = "alloc")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))]
|
||||||
mod alloc_only {
|
mod alloc_only {
|
||||||
#[cfg(feature = "std")]
|
use crate::alloc::alloc;
|
||||||
use std::alloc;
|
|
||||||
#[cfg(not(feature = "std"))]
|
use core::marker::PhantomData;
|
||||||
use alloc::alloc;
|
|
||||||
|
use super::private;
|
||||||
|
use crate::ffi::{self, types::{c_uint, c_void}};
|
||||||
|
use crate::{Secp256k1, Signing, Verification, Context, AlignedType};
|
||||||
|
|
||||||
#[cfg(feature = "rand-std")]
|
#[cfg(feature = "rand-std")]
|
||||||
use rand;
|
use rand;
|
||||||
|
@ -119,8 +121,7 @@ mod alloc_only {
|
||||||
impl private::Sealed for All {}
|
impl private::Sealed for All {}
|
||||||
impl private::Sealed for VerifyOnly {}
|
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.
|
/// Represents the set of capabilities needed for signing.
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
|
30
src/ecdh.rs
30
src/ecdh.rs
|
@ -15,14 +15,11 @@
|
||||||
//! Support for shared secret computations.
|
//! Support for shared secret computations.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use core::{ptr, str};
|
use core::{borrow::Borrow, ptr, str};
|
||||||
use core::borrow::Borrow;
|
|
||||||
|
|
||||||
use {Error, from_hex};
|
|
||||||
use key::{SecretKey, PublicKey};
|
|
||||||
use ffi::{self, CPtr};
|
|
||||||
use secp256k1_sys::types::{c_int, c_uchar, c_void};
|
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`).
|
// The logic for displaying shared secrets relies on this (see `secret.rs`).
|
||||||
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
|
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
|
||||||
|
@ -97,7 +94,7 @@ impl str::FromStr for SharedSecret {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
fn from_str(s: &str) -> Result<SharedSecret, Error> {
|
fn from_str(s: &str) -> Result<SharedSecret, Error> {
|
||||||
let mut res = [0u8; SHARED_SECRET_SIZE];
|
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)),
|
Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)),
|
||||||
_ => Err(Error::InvalidSharedSecret)
|
_ => 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> {
|
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
if s.is_human_readable() {
|
if s.is_human_readable() {
|
||||||
let mut buf = [0u8; SHARED_SECRET_SIZE * 2];
|
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 {
|
} else {
|
||||||
s.serialize_bytes(&self.as_ref()[..])
|
s.serialize_bytes(&self.as_ref()[..])
|
||||||
}
|
}
|
||||||
|
@ -204,13 +201,13 @@ impl<'de> ::serde::Deserialize<'de> for SharedSecret {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use super::super::Secp256k1;
|
|
||||||
|
|
||||||
#[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::Secp256k1;
|
||||||
|
use super::SharedSecret;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))]
|
||||||
fn ecdh() {
|
fn ecdh() {
|
||||||
|
@ -230,7 +227,7 @@ mod tests {
|
||||||
let x = [5u8; 32];
|
let x = [5u8; 32];
|
||||||
let y = [7u8; 32];
|
let y = [7u8; 32];
|
||||||
let mut output = [0u8; 64];
|
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);
|
assert_eq!(res, 1);
|
||||||
let mut new_x = [0u8; 32];
|
let mut new_x = [0u8; 32];
|
||||||
let mut new_y = [0u8; 32];
|
let mut new_y = [0u8; 32];
|
||||||
|
@ -244,7 +241,8 @@ mod tests {
|
||||||
#[cfg(not(fuzzing))]
|
#[cfg(not(fuzzing))]
|
||||||
#[cfg(all(feature="rand-std", feature = "std", feature = "bitcoin_hashes"))]
|
#[cfg(all(feature="rand-std", feature = "std", feature = "bitcoin_hashes"))]
|
||||||
fn bitcoin_hashes_and_sys_generate_same_secret() {
|
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 s = Secp256k1::signing_only();
|
||||||
let (sk1, _) = s.generate_keypair(&mut thread_rng());
|
let (sk1, _) = s.generate_keypair(&mut thread_rng());
|
||||||
|
@ -292,11 +290,13 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(all(test, feature = "unstable"))]
|
#[cfg(all(test, feature = "unstable"))]
|
||||||
mod benches {
|
mod benches {
|
||||||
use rand::thread_rng;
|
|
||||||
use test::{Bencher, black_box};
|
use test::{Bencher, black_box};
|
||||||
|
|
||||||
|
use rand::thread_rng;
|
||||||
|
|
||||||
|
use crate::Secp256k1;
|
||||||
|
|
||||||
use super::SharedSecret;
|
use super::SharedSecret;
|
||||||
use super::super::Secp256k1;
|
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
pub fn bench_ecdh(bh: &mut Bencher) {
|
pub fn bench_ecdh(bh: &mut Bencher) {
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
use core::{fmt, str, ops, ptr, mem};
|
use core::{fmt, str, ops, ptr, mem};
|
||||||
|
|
||||||
use {Signing, Verification, Message, PublicKey, Secp256k1, SecretKey, from_hex, Error, ffi};
|
use crate::{Signing, Verification, Message, PublicKey, Secp256k1, SecretKey, from_hex, Error, ffi};
|
||||||
use ffi::CPtr;
|
use crate::ffi::CPtr;
|
||||||
|
|
||||||
#[cfg(feature = "recovery")]
|
#[cfg(feature = "recovery")]
|
||||||
mod recovery;
|
mod recovery;
|
||||||
|
@ -13,7 +13,7 @@ mod recovery;
|
||||||
pub use self::recovery::{RecoveryId, RecoverableSignature};
|
pub use self::recovery::{RecoveryId, RecoverableSignature};
|
||||||
|
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
use SECP256K1;
|
use crate::SECP256K1;
|
||||||
|
|
||||||
/// An ECDSA signature
|
/// An ECDSA signature
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -120,7 +120,7 @@ impl SerializedSignature {
|
||||||
/// Convert the serialized signature into the Signature struct.
|
/// Convert the serialized signature into the Signature struct.
|
||||||
/// (This DER deserializes it)
|
/// (This DER deserializes it)
|
||||||
pub fn to_signature(&self) -> Result<Signature, Error> {
|
pub fn to_signature(&self) -> Result<Signature, Error> {
|
||||||
Signature::from_der(&self)
|
Signature::from_der(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a SerializedSignature from a Signature.
|
/// Create a SerializedSignature from a Signature.
|
||||||
|
@ -304,8 +304,8 @@ impl From<ffi::Signature> for Signature {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl ::serde::Serialize for Signature {
|
impl serde::Serialize for Signature {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
if s.is_human_readable() {
|
if s.is_human_readable() {
|
||||||
s.collect_str(self)
|
s.collect_str(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -316,14 +316,14 @@ impl ::serde::Serialize for Signature {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl<'de> ::serde::Deserialize<'de> for Signature {
|
impl<'de> serde::Deserialize<'de> for Signature {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
if d.is_human_readable() {
|
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"
|
"a hex string representing a DER encoded Signature"
|
||||||
))
|
))
|
||||||
} else {
|
} 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",
|
"raw byte stream, that represents a DER encoded Signature",
|
||||||
Signature::from_der
|
Signature::from_der
|
||||||
))
|
))
|
||||||
|
@ -467,12 +467,11 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
||||||
/// # use secp256k1::rand::rngs::OsRng;
|
/// # use secp256k1::rand::thread_rng;
|
||||||
/// # use secp256k1::{Secp256k1, Message, Error};
|
/// # use secp256k1::{Secp256k1, Message, Error};
|
||||||
/// #
|
/// #
|
||||||
/// # let secp = Secp256k1::new();
|
/// # let secp = Secp256k1::new();
|
||||||
/// # let mut rng = OsRng::new().expect("OsRng");
|
/// # let (secret_key, public_key) = secp.generate_keypair(&mut thread_rng());
|
||||||
/// # let (secret_key, public_key) = secp.generate_keypair(&mut 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(&message, &secret_key);
|
/// let sig = secp.sign(&message, &secret_key);
|
||||||
|
@ -496,12 +495,11 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
|
||||||
/// # use secp256k1::rand::rngs::OsRng;
|
/// # use secp256k1::rand::thread_rng;
|
||||||
/// # use secp256k1::{Secp256k1, Message, Error};
|
/// # use secp256k1::{Secp256k1, Message, Error};
|
||||||
/// #
|
/// #
|
||||||
/// # let secp = Secp256k1::new();
|
/// # let secp = Secp256k1::new();
|
||||||
/// # let mut rng = OsRng::new().expect("OsRng");
|
/// # let (secret_key, public_key) = secp.generate_keypair(&mut thread_rng());
|
||||||
/// # let (secret_key, public_key) = secp.generate_keypair(&mut 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);
|
||||||
|
|
|
@ -18,12 +18,10 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use key;
|
use crate::{key, Secp256k1, Message, Error, Verification, Signing, ecdsa::Signature};
|
||||||
use super::ffi as super_ffi;
|
use super::ffi as super_ffi;
|
||||||
use self::super_ffi::CPtr;
|
use self::super_ffi::CPtr;
|
||||||
use ffi::recovery as ffi;
|
use crate::ffi::recovery as ffi;
|
||||||
use super::*;
|
|
||||||
use {Verification, Secp256k1, Signing, Message};
|
|
||||||
|
|
||||||
/// A tag used for recovering the public key from a compact signature.
|
/// A tag used for recovering the public key from a compact signature.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -38,7 +36,7 @@ impl RecoveryId {
|
||||||
/// Allows library users to create valid recovery IDs from i32.
|
/// Allows library users to create valid recovery IDs from i32.
|
||||||
pub fn from_i32(id: i32) -> Result<RecoveryId, Error> {
|
pub fn from_i32(id: i32) -> Result<RecoveryId, Error> {
|
||||||
match id {
|
match id {
|
||||||
0 | 1 | 2 | 3 => Ok(RecoveryId(id)),
|
0..=3 => Ok(RecoveryId(id)),
|
||||||
_ => Err(Error::InvalidRecoveryId)
|
_ => Err(Error::InvalidRecoveryId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +125,7 @@ impl RecoverableSignature {
|
||||||
#[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 fn recover(&self, msg: &Message) -> Result<key::PublicKey, Error> {
|
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)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use rand::{RngCore, thread_rng};
|
use rand::{RngCore, thread_rng};
|
||||||
use key::SecretKey;
|
|
||||||
|
use crate::{Error, SecretKey, Secp256k1, Message};
|
||||||
|
use super::{RecoveryId, RecoverableSignature};
|
||||||
|
|
||||||
#[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;
|
||||||
|
|
193
src/key.rs
193
src/key.rs
|
@ -16,22 +16,19 @@
|
||||||
//! Public and secret keys.
|
//! Public and secret keys.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
#[cfg(any(test, feature = "rand"))] use rand::Rng;
|
|
||||||
|
|
||||||
use core::{fmt, ptr, str};
|
use core::{fmt, ptr, str};
|
||||||
use core::ops::BitXor;
|
use core::ops::BitXor;
|
||||||
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
use super::{from_hex, Secp256k1};
|
use crate::{constants, from_hex, Secp256k1, Signing, Verification};
|
||||||
use super::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey};
|
use crate::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey};
|
||||||
use ::{Signing};
|
use crate::ffi::{self, CPtr, impl_array_newtype};
|
||||||
use Verification;
|
use crate::ffi::types::c_uint;
|
||||||
use constants;
|
|
||||||
use ffi::{self, CPtr};
|
|
||||||
|
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
use {Message, ecdsa, SECP256K1};
|
use crate::{Message, ecdsa, SECP256K1};
|
||||||
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
||||||
use schnorr;
|
use crate::schnorr;
|
||||||
|
|
||||||
/// Secret 256-bit key used as `x` in an ECDSA signature.
|
/// 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"))]
|
#[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];
|
let mut ret = [0u8; 32];
|
||||||
rng.fill_bytes(&mut ret);
|
rng.fill_bytes(&mut ret);
|
||||||
ret
|
ret
|
||||||
|
@ -142,7 +139,7 @@ impl SecretKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(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);
|
let mut data = random_32_bytes(rng);
|
||||||
unsafe {
|
unsafe {
|
||||||
while ffi::secp256k1_ec_seckey_verify(
|
while ffi::secp256k1_ec_seckey_verify(
|
||||||
|
@ -166,9 +163,8 @@ impl SecretKey {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice(data: &[u8])-> Result<SecretKey, Error> {
|
pub fn from_slice(data: &[u8])-> Result<SecretKey, Error> {
|
||||||
match data.len() {
|
match <[u8; constants::SECRET_KEY_SIZE]>::try_from(data) {
|
||||||
constants::SECRET_KEY_SIZE => {
|
Ok(data) => {
|
||||||
let mut ret = [0u8; constants::SECRET_KEY_SIZE];
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_seckey_verify(
|
if ffi::secp256k1_ec_seckey_verify(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
@ -178,10 +174,9 @@ impl SecretKey {
|
||||||
return Err(InvalidSecretKey);
|
return Err(InvalidSecretKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret[..].copy_from_slice(data);
|
Ok(SecretKey(data))
|
||||||
Ok(SecretKey(ret))
|
|
||||||
}
|
}
|
||||||
_ => Err(InvalidSecretKey)
|
Err(_) => Err(InvalidSecretKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,11 +316,11 @@ impl SecretKey {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl ::serde::Serialize for SecretKey {
|
impl serde::Serialize for SecretKey {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
if s.is_human_readable() {
|
if s.is_human_readable() {
|
||||||
let mut buf = [0u8; constants::SECRET_KEY_SIZE * 2];
|
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 {
|
} else {
|
||||||
s.serialize_bytes(&self[..])
|
s.serialize_bytes(&self[..])
|
||||||
}
|
}
|
||||||
|
@ -334,8 +329,8 @@ impl ::serde::Serialize for SecretKey {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl<'de> ::serde::Deserialize<'de> for SecretKey {
|
impl<'de> serde::Deserialize<'de> for SecretKey {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
||||||
"a hex string representing 32 byte SecretKey"
|
"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.
|
/// represented by only a single bit, as x determines it up to one bit.
|
||||||
pub fn serialize(&self) -> [u8; constants::PUBLIC_KEY_SIZE] {
|
pub fn serialize(&self) -> [u8; constants::PUBLIC_KEY_SIZE] {
|
||||||
let mut ret = [0u8; constants::PUBLIC_KEY_SIZE];
|
let mut ret = [0u8; constants::PUBLIC_KEY_SIZE];
|
||||||
|
self.serialize_internal(&mut ret, ffi::SECP256K1_SER_COMPRESSED);
|
||||||
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());
|
|
||||||
}
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Serializes the key as a byte-encoded pair of values, in uncompressed form.
|
/// Serializes the key as a byte-encoded pair of values, in uncompressed form.
|
||||||
pub fn serialize_uncompressed(&self) -> [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] {
|
pub fn serialize_uncompressed(&self) -> [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] {
|
||||||
let mut ret = [0u8; 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 {
|
#[inline(always)]
|
||||||
let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as usize;
|
fn serialize_internal(&self, ret: &mut [u8], flag: c_uint) {
|
||||||
let err = ffi::secp256k1_ec_pubkey_serialize(
|
let mut ret_len = ret.len();
|
||||||
|
let res = unsafe {
|
||||||
|
ffi::secp256k1_ec_pubkey_serialize(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
ret.as_mut_c_ptr(),
|
ret.as_mut_c_ptr(),
|
||||||
&mut ret_len,
|
&mut ret_len,
|
||||||
self.as_c_ptr(),
|
self.as_c_ptr(),
|
||||||
ffi::SECP256K1_SER_UNCOMPRESSED,
|
flag,
|
||||||
);
|
)
|
||||||
debug_assert_eq!(err, 1);
|
};
|
||||||
|
debug_assert_eq!(res, 1);
|
||||||
debug_assert_eq!(ret_len, ret.len());
|
debug_assert_eq!(ret_len, ret.len());
|
||||||
}
|
}
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Negates the public key in place.
|
/// Negates the public key in place.
|
||||||
|
@ -671,8 +659,8 @@ impl From<ffi::PublicKey> for PublicKey {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl ::serde::Serialize for PublicKey {
|
impl serde::Serialize for PublicKey {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
if s.is_human_readable() {
|
if s.is_human_readable() {
|
||||||
s.collect_str(self)
|
s.collect_str(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -683,8 +671,8 @@ impl ::serde::Serialize for PublicKey {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl<'de> ::serde::Deserialize<'de> for PublicKey {
|
impl<'de> serde::Deserialize<'de> for PublicKey {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
||||||
"an ASCII hex string representing a public key"
|
"an ASCII hex string representing a public key"
|
||||||
|
@ -699,13 +687,13 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd 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())
|
self.serialize().partial_cmp(&other.serialize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for PublicKey {
|
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())
|
self.serialize().cmp(&other.serialize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -837,7 +825,7 @@ impl KeyPair {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, 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 random_32_bytes = || {
|
||||||
let mut ret = [0u8; 32];
|
let mut ret = [0u8; 32];
|
||||||
rng.fill_bytes(&mut ret);
|
rng.fill_bytes(&mut ret);
|
||||||
|
@ -992,11 +980,11 @@ impl str::FromStr for KeyPair {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl ::serde::Serialize for KeyPair {
|
impl serde::Serialize for KeyPair {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
if s.is_human_readable() {
|
if s.is_human_readable() {
|
||||||
let mut buf = [0u8; constants::SECRET_KEY_SIZE * 2];
|
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"))
|
.expect("fixed-size hex serialization"))
|
||||||
} else {
|
} else {
|
||||||
s.serialize_bytes(&self.0[..])
|
s.serialize_bytes(&self.0[..])
|
||||||
|
@ -1006,8 +994,8 @@ impl ::serde::Serialize for KeyPair {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl<'de> ::serde::Deserialize<'de> for KeyPair {
|
impl<'de> serde::Deserialize<'de> for KeyPair {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
||||||
"a hex string representing 32 byte KeyPair"
|
"a hex string representing 32 byte KeyPair"
|
||||||
|
@ -1360,7 +1348,7 @@ impl fmt::Display for InvalidParityValue {
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[cfg_attr(docsrs, doc(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 {
|
impl From<InvalidParityValue> for Error {
|
||||||
fn from(error: InvalidParityValue) -> Self {
|
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.
|
/// The parity is serialized as `u8` - `0` for even, `1` for odd.
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl ::serde::Serialize for Parity {
|
impl serde::Serialize for Parity {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
s.serialize_u8(self.to_u8())
|
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.
|
/// The parity is deserialized as `u8` - `0` for even, `1` for odd.
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl<'de> ::serde::Deserialize<'de> for Parity {
|
impl<'de> serde::Deserialize<'de> for Parity {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
struct Visitor;
|
struct Visitor;
|
||||||
|
|
||||||
impl<'de> ::serde::de::Visitor<'de> for Visitor
|
impl<'de> serde::de::Visitor<'de> for Visitor
|
||||||
{
|
{
|
||||||
type Value = Parity;
|
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>
|
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;
|
use serde::de::Unexpected;
|
||||||
|
|
||||||
|
@ -1425,8 +1413,8 @@ impl From<ffi::XOnlyPublicKey> for XOnlyPublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<::key::PublicKey> for XOnlyPublicKey {
|
impl From<PublicKey> for XOnlyPublicKey {
|
||||||
fn from(src: ::key::PublicKey) -> XOnlyPublicKey {
|
fn from(src: PublicKey) -> XOnlyPublicKey {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut pk = ffi::XOnlyPublicKey::new();
|
let mut pk = ffi::XOnlyPublicKey::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1445,8 +1433,8 @@ impl From<::key::PublicKey> for XOnlyPublicKey {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl ::serde::Serialize for XOnlyPublicKey {
|
impl serde::Serialize for XOnlyPublicKey {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
if s.is_human_readable() {
|
if s.is_human_readable() {
|
||||||
s.collect_str(self)
|
s.collect_str(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1457,8 +1445,8 @@ impl ::serde::Serialize for XOnlyPublicKey {
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
impl<'de> ::serde::Deserialize<'de> for XOnlyPublicKey {
|
impl<'de> serde::Deserialize<'de> for XOnlyPublicKey {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
||||||
"a hex string representing 32 byte schnorr public key"
|
"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"))]
|
#[cfg(all(feature = "global-context", feature = "serde"))]
|
||||||
pub mod serde_keypair {
|
pub mod serde_keypair {
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use key::KeyPair;
|
use crate::key::{KeyPair, SecretKey};
|
||||||
use key::SecretKey;
|
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn serialize<S>(key: &KeyPair, serializer: S) -> Result<S::Ok, S::Error>
|
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)?;
|
let secret_key = SecretKey::deserialize(deserializer)?;
|
||||||
|
|
||||||
Ok(KeyPair::from_secret_key(
|
Ok(KeyPair::from_secret_key(
|
||||||
&::SECP256K1,
|
&crate::SECP256K1,
|
||||||
&secret_key,
|
&secret_key,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -1514,23 +1501,18 @@ pub mod serde_keypair {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
|
||||||
use core::iter;
|
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
use rand::{Error, ErrorKind, RngCore, thread_rng};
|
use rand::{Error, RngCore, thread_rng, rngs::mock::StepRng};
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
|
||||||
use rand_core::impls;
|
|
||||||
|
|
||||||
use constants;
|
|
||||||
use Error::{InvalidPublicKey, InvalidSecretKey};
|
|
||||||
|
|
||||||
#[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 super::{XOnlyPublicKey, PublicKey, Secp256k1, SecretKey, KeyPair, Parity};
|
||||||
|
use crate::{constants, from_hex, to_hex};
|
||||||
|
use crate::Error::{InvalidPublicKey, InvalidSecretKey};
|
||||||
|
|
||||||
macro_rules! hex {
|
macro_rules! hex {
|
||||||
($hex:expr) => ({
|
($hex:expr) => ({
|
||||||
let mut result = vec![0; $hex.len() / 2];
|
let mut result = vec![0; $hex.len() / 2];
|
||||||
|
@ -1601,7 +1583,6 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
fn test_out_of_range() {
|
fn test_out_of_range() {
|
||||||
|
|
||||||
struct BadRng(u8);
|
struct BadRng(u8);
|
||||||
impl RngCore for BadRng {
|
impl RngCore for BadRng {
|
||||||
fn next_u32(&mut self) -> u32 { unimplemented!() }
|
fn next_u32(&mut self) -> u32 { unimplemented!() }
|
||||||
|
@ -1694,28 +1675,9 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))]
|
||||||
fn test_debug_output() {
|
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 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),
|
assert_eq!(&format!("{:?}", sk),
|
||||||
"SecretKey(#d3e0c51a23169bb5)");
|
"SecretKey(#d3e0c51a23169bb5)");
|
||||||
|
@ -1781,7 +1743,7 @@ mod test {
|
||||||
assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err());
|
assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err());
|
||||||
assert!(PublicKey::from_str("xx0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").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!(SecretKey::from_str(&long_str).is_err());
|
||||||
assert!(PublicKey::from_str(&long_str).is_err());
|
assert!(PublicKey::from_str(&long_str).is_err());
|
||||||
}
|
}
|
||||||
|
@ -1792,26 +1754,9 @@ mod test {
|
||||||
#[cfg(not(fuzzing))]
|
#[cfg(not(fuzzing))]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
fn test_pubkey_serialize() {
|
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 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()[..],
|
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][..]);
|
&[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()[..],
|
assert_eq!(&pk1.serialize()[..],
|
||||||
|
@ -2095,7 +2040,7 @@ mod test {
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use serde_test::{Configure, Token, assert_tokens};
|
use serde_test::{Configure, Token, assert_tokens};
|
||||||
use super::serde_keypair;
|
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
|
// 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.
|
// here, so they are implemented manually to be able to test the behaviour.
|
||||||
|
@ -2125,7 +2070,7 @@ mod test {
|
||||||
01010101010101010001020304050607ffff0000ffff00006363636363636363\
|
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::BorrowedBytes(&SK_BYTES[..])]);
|
||||||
assert_tokens(&sk.compact(), &[Token::Bytes(&SK_BYTES)]);
|
assert_tokens(&sk.compact(), &[Token::Bytes(&SK_BYTES)]);
|
||||||
|
|
122
src/lib.rs
122
src/lib.rs
|
@ -47,8 +47,7 @@
|
||||||
//! use secp256k1::hashes::sha256;
|
//! use secp256k1::hashes::sha256;
|
||||||
//!
|
//!
|
||||||
//! let secp = Secp256k1::new();
|
//! let secp = Secp256k1::new();
|
||||||
//! let mut rng = OsRng::new().expect("OsRng");
|
//! let (secret_key, public_key) = secp.generate_keypair(&mut OsRng);
|
||||||
//! let (secret_key, public_key) = secp.generate_keypair(&mut 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 = secp.sign_ecdsa(&message, &secret_key);
|
//! let sig = secp.sign_ecdsa(&message, &secret_key);
|
||||||
|
@ -150,47 +149,19 @@
|
||||||
//! * `bitcoin_hashes` - enables interaction with the `bitcoin-hashes` crate (e.g. conversions).
|
//! * `bitcoin_hashes` - enables interaction with the `bitcoin-hashes` crate (e.g. conversions).
|
||||||
|
|
||||||
// Coding conventions
|
// Coding conventions
|
||||||
#![deny(non_upper_case_globals)]
|
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)]
|
||||||
#![deny(non_camel_case_types)]
|
#![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)]
|
||||||
#![deny(non_snake_case)]
|
|
||||||
#![deny(unused_mut)]
|
|
||||||
#![warn(missing_docs)]
|
|
||||||
#![warn(missing_copy_implementations)]
|
|
||||||
#![warn(missing_debug_implementations)]
|
|
||||||
|
|
||||||
|
|
||||||
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
||||||
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
|
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![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")]
|
#[cfg(feature = "alloc")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
#[cfg(any(test, feature = "std"))]
|
||||||
|
extern crate core;
|
||||||
|
#[cfg(all(test, feature = "unstable"))]
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
@ -206,18 +177,28 @@ pub mod schnorr;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
mod serde_util;
|
mod serde_util;
|
||||||
|
|
||||||
pub use key::*;
|
#[cfg(any(test, feature = "rand"))]
|
||||||
pub use context::*;
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
use core::marker::PhantomData;
|
pub use rand;
|
||||||
use core::{mem, fmt, str};
|
#[cfg(feature = "serde")]
|
||||||
use ffi::{CPtr, types::AlignedType};
|
#[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(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;
|
||||||
|
|
||||||
|
use core::{fmt, str, mem, marker::PhantomData};
|
||||||
|
use crate::ffi::{CPtr, impl_array_newtype, types::AlignedType};
|
||||||
#[cfg(feature = "bitcoin_hashes")]
|
#[cfg(feature = "bitcoin_hashes")]
|
||||||
use hashes::Hash;
|
use crate::hashes::Hash;
|
||||||
|
|
||||||
// Backwards compatible changes
|
// Backwards compatible changes
|
||||||
/// Schnorr Signature related methods.
|
/// Schnorr Signature related methods.
|
||||||
|
@ -225,13 +206,13 @@ use hashes::Hash;
|
||||||
pub mod schnorrsig {
|
pub mod schnorrsig {
|
||||||
#[deprecated(since = "0.21.0", note = "Use crate::XOnlyPublicKey instead.")]
|
#[deprecated(since = "0.21.0", note = "Use crate::XOnlyPublicKey instead.")]
|
||||||
/// backwards compatible re-export of xonly key
|
/// backwards compatible re-export of xonly key
|
||||||
pub type PublicKey = super::XOnlyPublicKey;
|
pub type PublicKey = crate::key::XOnlyPublicKey;
|
||||||
/// backwards compatible re-export of keypair
|
/// backwards compatible re-export of keypair
|
||||||
#[deprecated(since = "0.21.0", note = "Use crate::KeyPair instead.")]
|
#[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
|
/// backwards compatible re-export of schnorr signatures
|
||||||
#[deprecated(since = "0.21.0", note = "Use schnorr::Signature instead.")]
|
#[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.")]
|
#[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).
|
/// [libsecp256k1](https://github.com/bitcoin-core/secp256k1/commit/d2275795ff22a6f4738869f5528fbbb61738aa48).
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(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];
|
let mut seed = [0u8; 32];
|
||||||
rng.fill_bytes(&mut seed);
|
rng.fill_bytes(&mut seed);
|
||||||
self.seeded_randomize(&seed);
|
self.seeded_randomize(&seed);
|
||||||
|
@ -501,7 +482,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(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) {
|
-> (key::SecretKey, key::PublicKey) {
|
||||||
let sk = key::SecretKey::new(rng);
|
let sk = key::SecretKey::new(rng);
|
||||||
let pk = key::PublicKey::from_secret_key(self, &sk);
|
let pk = key::PublicKey::from_secret_key(self, &sk);
|
||||||
|
@ -513,7 +494,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(all(feature = "global-context", feature = "rand"))]
|
#[cfg(all(feature = "global-context", feature = "rand"))]
|
||||||
#[cfg_attr(docsrs, doc(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)
|
SECP256K1.generate_keypair(rng)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,14 +550,18 @@ fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use std::marker::PhantomData;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use rand::{RngCore, thread_rng};
|
use rand::{RngCore, thread_rng};
|
||||||
use core::str::FromStr;
|
|
||||||
use ffi::types::AlignedType;
|
|
||||||
|
|
||||||
#[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::{constants, ecdsa, from_hex, to_hex, Message, PublicKey, Secp256k1, SecretKey, Error};
|
||||||
|
use crate::context::*;
|
||||||
|
use crate::ffi::{self, types::AlignedType};
|
||||||
|
|
||||||
macro_rules! hex {
|
macro_rules! hex {
|
||||||
($hex:expr) => ({
|
($hex:expr) => ({
|
||||||
let mut result = vec![0; $hex.len() / 2];
|
let mut result = vec![0; $hex.len() / 2];
|
||||||
|
@ -1038,6 +1023,7 @@ mod tests {
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_global_context() {
|
fn test_global_context() {
|
||||||
|
use crate::SECP256K1;
|
||||||
let sk_data = hex!("e6dd32f8761625f105c39a39f19370b3521d845a12456d60ce44debd0a362641");
|
let sk_data = hex!("e6dd32f8761625f105c39a39f19370b3521d845a12456d60ce44debd0a362641");
|
||||||
let sk = SecretKey::from_slice(&sk_data).unwrap();
|
let sk = SecretKey::from_slice(&sk_data).unwrap();
|
||||||
let msg_data = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
|
let msg_data = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
|
||||||
|
@ -1054,8 +1040,7 @@ mod tests {
|
||||||
#[cfg(feature = "bitcoin_hashes")]
|
#[cfg(feature = "bitcoin_hashes")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_hash() {
|
fn test_from_hash() {
|
||||||
use hashes;
|
use crate::hashes::{self, Hash};
|
||||||
use hashes::Hash;
|
|
||||||
|
|
||||||
let test_bytes = "Hello world!".as_bytes();
|
let test_bytes = "Hello world!".as_bytes();
|
||||||
|
|
||||||
|
@ -1079,40 +1064,19 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(all(test, feature = "unstable"))]
|
#[cfg(all(test, feature = "unstable"))]
|
||||||
mod benches {
|
mod benches {
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
use test::{Bencher, black_box};
|
use test::{Bencher, black_box};
|
||||||
|
|
||||||
use super::{Secp256k1, Message};
|
use rand::{RngCore, thread_rng};
|
||||||
|
use rand::rngs::mock::StepRng;
|
||||||
|
|
||||||
|
use super::{Message, Secp256k1};
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
pub fn generate(bh: &mut Bencher) {
|
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 s = Secp256k1::new();
|
||||||
let mut r = CounterRng(0);
|
let mut r = StepRng::new(1, 1);
|
||||||
bh.iter( || {
|
bh.iter( || {
|
||||||
let (sk, pk) = s.generate_keypair(&mut r);
|
let (sk, pk) = s.generate_keypair(&mut r);
|
||||||
black_box(sk);
|
black_box(sk);
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
macro_rules! impl_pretty_debug {
|
macro_rules! impl_pretty_debug {
|
||||||
($thing:ident) => {
|
($thing:ident) => {
|
||||||
impl ::core::fmt::Debug for $thing {
|
impl core::fmt::Debug for $thing {
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
write!(f, "{}(", stringify!($thing))?;
|
write!(f, "{}(", stringify!($thing))?;
|
||||||
for i in &self[..] {
|
for i in &self[..] {
|
||||||
write!(f, "{:02x}", i)?;
|
write!(f, "{:02x}", i)?;
|
||||||
|
|
|
@ -2,19 +2,17 @@
|
||||||
//! Support for Schnorr signatures.
|
//! Support for Schnorr signatures.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
#[cfg(any(test, feature = "rand-std"))]
|
use core::{fmt, ptr, str};
|
||||||
use rand::thread_rng;
|
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
|
|
||||||
use super::{from_hex, Error};
|
use crate::{constants, Error, from_hex, Message, Secp256k1, Signing, Verification};
|
||||||
use core::{fmt, ptr, str};
|
use crate::key::{KeyPair, XOnlyPublicKey};
|
||||||
use ffi::{self, CPtr};
|
use crate::ffi::{self, CPtr, impl_array_newtype};
|
||||||
use {constants, Secp256k1};
|
|
||||||
use {Message, Signing, Verification, KeyPair, XOnlyPublicKey};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
||||||
use SECP256K1;
|
use crate::SECP256K1;
|
||||||
|
|
||||||
/// Represents a Schnorr signature.
|
/// Represents a Schnorr signature.
|
||||||
pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
|
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);
|
impl_pretty_debug!(Signature);
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
impl serde::Serialize for Signature {
|
||||||
impl ::serde::Serialize for Signature {
|
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
|
||||||
if s.is_human_readable() {
|
if s.is_human_readable() {
|
||||||
s.collect_str(self)
|
s.collect_str(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -34,9 +31,8 @@ impl ::serde::Serialize for Signature {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
impl<'de> serde::Deserialize<'de> for Signature {
|
||||||
impl<'de> ::serde::Deserialize<'de> for Signature {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
||||||
"a hex string representing 64 byte schnorr signature"
|
"a hex string representing 64 byte schnorr signature"
|
||||||
|
@ -139,8 +135,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
#[cfg(any(test, feature = "rand-std"))]
|
#[cfg(any(test, 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 {
|
||||||
let mut rng = thread_rng();
|
self.sign_schnorr_with_rng(msg, keypair, &mut rand::thread_rng())
|
||||||
self.sign_schnorr_with_rng(msg, keypair, &mut rng)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a schnorr signature without using any auxiliary random data.
|
/// Create a schnorr signature without using any auxiliary random data.
|
||||||
|
@ -276,21 +271,16 @@ impl <C: Signing> Secp256k1<C> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::iter;
|
use core::str::FromStr;
|
||||||
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 rand::{RngCore, rngs::ThreadRng, 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;
|
||||||
|
|
||||||
|
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
|
||||||
|
use crate::schnorr::{KeyPair, XOnlyPublicKey, Signature};
|
||||||
|
use crate::Error::InvalidPublicKey;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
||||||
|
@ -338,7 +328,7 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(all(feature = "std", feature = "rand-std"))]
|
||||||
fn sign_helper(
|
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();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -429,8 +419,8 @@ mod tests {
|
||||||
let keypair = KeyPair::from_seckey_str(&secp, sk_str).unwrap();
|
let keypair = KeyPair::from_seckey_str(&secp, sk_str).unwrap();
|
||||||
let sk = SecretKey::from_keypair(&keypair);
|
let sk = SecretKey::from_keypair(&keypair);
|
||||||
assert_eq!(SecretKey::from_str(sk_str).unwrap(), sk);
|
assert_eq!(SecretKey::from_str(sk_str).unwrap(), sk);
|
||||||
let pk = ::key::PublicKey::from_keypair(&keypair);
|
let pk = crate::key::PublicKey::from_keypair(&keypair);
|
||||||
assert_eq!(::key::PublicKey::from_secret_key(&secp, &sk), pk);
|
assert_eq!(crate::key::PublicKey::from_secret_key(&secp, &sk), pk);
|
||||||
let (xpk, _parity) = keypair.x_only_public_key();
|
let (xpk, _parity) = keypair.x_only_public_key();
|
||||||
assert_eq!(XOnlyPublicKey::from(pk), xpk);
|
assert_eq!(XOnlyPublicKey::from(pk), xpk);
|
||||||
}
|
}
|
||||||
|
@ -515,7 +505,7 @@ mod tests {
|
||||||
)
|
)
|
||||||
.is_err());
|
.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());
|
assert!(XOnlyPublicKey::from_str(&long_str).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,26 +515,9 @@ mod tests {
|
||||||
#[cfg(not(fuzzing))]
|
#[cfg(not(fuzzing))]
|
||||||
#[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "rand", any(feature = "alloc", feature = "std")))]
|
||||||
fn test_pubkey_serialize() {
|
fn test_pubkey_serialize() {
|
||||||
struct DumbRng(u32);
|
use rand::rngs::mock::StepRng;
|
||||||
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 secp = Secp256k1::new();
|
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();
|
let (pk, _parity) = kp.x_only_public_key();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&pk.serialize()[..],
|
&pk.serialize()[..],
|
||||||
|
|
|
@ -14,25 +14,23 @@
|
||||||
|
|
||||||
//! Helpers for displaying secret values
|
//! Helpers for displaying secret values
|
||||||
|
|
||||||
use ::core::fmt;
|
use core::fmt;
|
||||||
use ::{SecretKey, KeyPair, to_hex};
|
use crate::{to_hex, constants::SECRET_KEY_SIZE, key::{SecretKey, KeyPair}, ecdh::SharedSecret};
|
||||||
use ecdh::SharedSecret;
|
|
||||||
use constants::SECRET_KEY_SIZE;
|
|
||||||
|
|
||||||
macro_rules! impl_display_secret {
|
macro_rules! impl_display_secret {
|
||||||
// Default hasher exists only in standard library and not alloc
|
// Default hasher exists only in standard library and not alloc
|
||||||
($thing:ident) => {
|
($thing:ident) => {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl ::core::fmt::Debug for $thing {
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
impl core::fmt::Debug for $thing {
|
||||||
use ::core::hash::Hasher;
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
use core::hash::Hasher;
|
||||||
const DEBUG_HASH_TAG: &[u8] = &[
|
const DEBUG_HASH_TAG: &[u8] = &[
|
||||||
0x66, 0xa6, 0x77, 0x1b, 0x9b, 0x6d, 0xae, 0xa1, 0xb2, 0xee, 0x4e, 0x07, 0x49,
|
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,
|
0x4a, 0xac, 0x87, 0xa9, 0xb8, 0x5b, 0x4b, 0x35, 0x02, 0xaa, 0x6d, 0x0f, 0x79,
|
||||||
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22
|
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22
|
||||||
]; // =SHA256(b"rust-secp256k1DEBUG");
|
]; // =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);
|
||||||
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"))]
|
#[cfg(all(not(feature = "std"), feature = "bitcoin_hashes"))]
|
||||||
impl ::core::fmt::Debug for $thing {
|
impl ::core::fmt::Debug for $thing {
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
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";
|
let tag = "rust-secp256k1DEBUG";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue