Merge pull request #253 from apoelstra/2020-11--schnorrsig-followup
BIP 0340 followups
This commit is contained in:
commit
11e9641d21
|
@ -106,13 +106,32 @@ impl_array_newtype!(PublicKey, c_uchar, 64);
|
||||||
impl_raw_debug!(PublicKey);
|
impl_raw_debug!(PublicKey);
|
||||||
|
|
||||||
impl PublicKey {
|
impl PublicKey {
|
||||||
/// Create a new (zeroed) public key usable for the FFI interface
|
/// Creates an "uninitialized" FFI public key which is zeroed out
|
||||||
pub fn new() -> PublicKey { PublicKey([0; 64]) }
|
///
|
||||||
}
|
/// If you pass this to any FFI functions, except as an out-pointer,
|
||||||
|
/// the result is likely to be an assertation failure and process
|
||||||
|
/// termination.
|
||||||
|
pub unsafe fn new() -> Self {
|
||||||
|
Self::from_array_unchecked([0; 64])
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for PublicKey {
|
/// Create a new public key usable for the FFI interface from raw bytes
|
||||||
fn default() -> Self {
|
///
|
||||||
PublicKey::new()
|
/// Does not check the validity of the underlying representation. If it is
|
||||||
|
/// invalid the result may be assertation failures (and process aborts) from
|
||||||
|
/// the underlying library. You should not use this method except with data
|
||||||
|
/// that you obtained from the FFI interface of the same version of this
|
||||||
|
/// library.
|
||||||
|
pub unsafe fn from_array_unchecked(data: [c_uchar; 64]) -> Self {
|
||||||
|
PublicKey(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the underlying FFI opaque representation of the public key
|
||||||
|
///
|
||||||
|
/// You should not use this unless you really know what you are doing. It is
|
||||||
|
/// essentially only useful for extending the FFI interface itself.
|
||||||
|
pub fn underlying_bytes(self) -> [c_uchar; 64] {
|
||||||
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,13 +148,32 @@ impl_array_newtype!(Signature, c_uchar, 64);
|
||||||
impl_raw_debug!(Signature);
|
impl_raw_debug!(Signature);
|
||||||
|
|
||||||
impl Signature {
|
impl Signature {
|
||||||
/// Create a new (zeroed) signature usable for the FFI interface
|
/// Creates an "uninitialized" FFI signature which is zeroed out
|
||||||
pub fn new() -> Signature { Signature([0; 64]) }
|
///
|
||||||
}
|
/// If you pass this to any FFI functions, except as an out-pointer,
|
||||||
|
/// the result is likely to be an assertation failure and process
|
||||||
|
/// termination.
|
||||||
|
pub unsafe fn new() -> Self {
|
||||||
|
Self::from_array_unchecked([0; 64])
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Signature {
|
/// Create a new signature usable for the FFI interface from raw bytes
|
||||||
fn default() -> Self {
|
///
|
||||||
Signature::new()
|
/// Does not check the validity of the underlying representation. If it is
|
||||||
|
/// invalid the result may be assertation failures (and process aborts) from
|
||||||
|
/// the underlying library. You should not use this method except with data
|
||||||
|
/// that you obtained from the FFI interface of the same version of this
|
||||||
|
/// library.
|
||||||
|
pub unsafe fn from_array_unchecked(data: [c_uchar; 64]) -> Self {
|
||||||
|
Signature(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the underlying FFI opaque representation of the signature
|
||||||
|
///
|
||||||
|
/// You should not use this unless you really know what you are doing. It is
|
||||||
|
/// essentially only useful for extending the FFI interface itself.
|
||||||
|
pub fn underlying_bytes(self) -> [c_uchar; 64] {
|
||||||
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +183,33 @@ impl_array_newtype!(XOnlyPublicKey, c_uchar, 64);
|
||||||
impl_raw_debug!(XOnlyPublicKey);
|
impl_raw_debug!(XOnlyPublicKey);
|
||||||
|
|
||||||
impl XOnlyPublicKey {
|
impl XOnlyPublicKey {
|
||||||
/// Create a new (zeroed) x-only public key usable for the FFI interface
|
/// Creates an "uninitialized" FFI x-only public key which is zeroed out
|
||||||
pub fn new() -> XOnlyPublicKey { XOnlyPublicKey([0; 64]) }
|
///
|
||||||
pub fn from_array(data: [c_uchar; 64]) -> XOnlyPublicKey {
|
/// If you pass this to any FFI functions, except as an out-pointer,
|
||||||
|
/// the result is likely to be an assertation failure and process
|
||||||
|
/// termination.
|
||||||
|
pub unsafe fn new() -> Self {
|
||||||
|
Self::from_array_unchecked([0; 64])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new x-only public key usable for the FFI interface from raw bytes
|
||||||
|
///
|
||||||
|
/// Does not check the validity of the underlying representation. If it is
|
||||||
|
/// invalid the result may be assertation failures (and process aborts) from
|
||||||
|
/// the underlying library. You should not use this method except with data
|
||||||
|
/// that you obtained from the FFI interface of the same version of this
|
||||||
|
/// library.
|
||||||
|
pub unsafe fn from_array_unchecked(data: [c_uchar; 64]) -> Self {
|
||||||
XOnlyPublicKey(data)
|
XOnlyPublicKey(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the underlying FFI opaque representation of the x-only public key
|
||||||
|
///
|
||||||
|
/// You should not use this unless you really know what you are doing. It is
|
||||||
|
/// essentially only useful for extending the FFI interface itself.
|
||||||
|
pub fn underlying_bytes(self) -> [c_uchar; 64] {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl hash::Hash for XOnlyPublicKey {
|
impl hash::Hash for XOnlyPublicKey {
|
||||||
|
@ -158,23 +218,39 @@ impl hash::Hash for XOnlyPublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for XOnlyPublicKey {
|
|
||||||
fn default() -> Self {
|
|
||||||
XOnlyPublicKey::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct KeyPair([c_uchar; 96]);
|
pub struct KeyPair([c_uchar; 96]);
|
||||||
impl_array_newtype!(KeyPair, c_uchar, 96);
|
impl_array_newtype!(KeyPair, c_uchar, 96);
|
||||||
impl_raw_debug!(KeyPair);
|
impl_raw_debug!(KeyPair);
|
||||||
|
|
||||||
impl KeyPair {
|
impl KeyPair {
|
||||||
/// Create a new (zeroed) key pair usable for the FFI interface
|
/// Creates an "uninitialized" FFI keypair which is zeroed out
|
||||||
pub fn new() -> KeyPair { KeyPair([0; 96]) }
|
///
|
||||||
pub fn from_array(data: [c_uchar; 96]) -> KeyPair {
|
/// If you pass this to any FFI functions, except as an out-pointer,
|
||||||
|
/// the result is likely to be an assertation failure and process
|
||||||
|
/// termination.
|
||||||
|
pub unsafe fn new() -> Self {
|
||||||
|
Self::from_array_unchecked([0; 96])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new keypair usable for the FFI interface from raw bytes
|
||||||
|
///
|
||||||
|
/// Does not check the validity of the underlying representation. If it is
|
||||||
|
/// invalid the result may be assertation failures (and process aborts) from
|
||||||
|
/// the underlying library. You should not use this method except with data
|
||||||
|
/// that you obtained from the FFI interface of the same version of this
|
||||||
|
/// library.
|
||||||
|
pub unsafe fn from_array_unchecked(data: [c_uchar; 96]) -> Self {
|
||||||
KeyPair(data)
|
KeyPair(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the underlying FFI opaque representation of the x-only public key
|
||||||
|
///
|
||||||
|
/// You should not use this unless you really know what you are doing. It is
|
||||||
|
/// essentially only useful for extending the FFI interface itself.
|
||||||
|
pub fn underlying_bytes(self) -> [c_uchar; 96] {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl hash::Hash for KeyPair {
|
impl hash::Hash for KeyPair {
|
||||||
|
@ -183,12 +259,6 @@ impl hash::Hash for KeyPair {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for KeyPair {
|
|
||||||
fn default() -> Self {
|
|
||||||
KeyPair::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "fuzztarget"))]
|
#[cfg(not(feature = "fuzztarget"))]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Default ECDH hash function
|
/// Default ECDH hash function
|
||||||
|
@ -591,7 +661,7 @@ impl<T> CPtr for [T] {
|
||||||
|
|
||||||
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() {
|
||||||
ptr::null::<Self::Target>() as *mut _
|
ptr::null_mut::<Self::Target>()
|
||||||
} else {
|
} else {
|
||||||
self.as_mut_ptr()
|
self.as_mut_ptr()
|
||||||
}
|
}
|
||||||
|
|
18
src/key.rs
18
src/key.rs
|
@ -219,13 +219,13 @@ impl PublicKey {
|
||||||
/// Obtains a raw const pointer suitable for use with FFI functions
|
/// Obtains a raw const pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_ptr(&self) -> *const ffi::PublicKey {
|
pub fn as_ptr(&self) -> *const ffi::PublicKey {
|
||||||
&self.0 as *const _
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut ffi::PublicKey {
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::PublicKey {
|
||||||
&mut self.0 as *mut _
|
&mut self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new public key from a secret key.
|
/// Creates a new public key from a secret key.
|
||||||
|
@ -233,23 +233,23 @@ impl PublicKey {
|
||||||
pub fn from_secret_key<C: Signing>(secp: &Secp256k1<C>,
|
pub fn from_secret_key<C: Signing>(secp: &Secp256k1<C>,
|
||||||
sk: &SecretKey)
|
sk: &SecretKey)
|
||||||
-> PublicKey {
|
-> PublicKey {
|
||||||
let mut pk = ffi::PublicKey::new();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut pk = ffi::PublicKey::new();
|
||||||
// We can assume the return value because it's not possible to construct
|
// We can assume the return value because it's not possible to construct
|
||||||
// an invalid `SecretKey` without transmute trickery or something
|
// an invalid `SecretKey` without transmute trickery or something
|
||||||
let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_c_ptr());
|
let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_c_ptr());
|
||||||
debug_assert_eq!(res, 1);
|
debug_assert_eq!(res, 1);
|
||||||
}
|
|
||||||
PublicKey(pk)
|
PublicKey(pk)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a public key directly from a slice
|
/// Creates a public key directly from a slice
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
|
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
|
||||||
if data.is_empty() {return Err(Error::InvalidPublicKey);}
|
if data.is_empty() {return Err(Error::InvalidPublicKey);}
|
||||||
|
|
||||||
let mut pk = ffi::PublicKey::new();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut pk = ffi::PublicKey::new();
|
||||||
if ffi::secp256k1_ec_pubkey_parse(
|
if ffi::secp256k1_ec_pubkey_parse(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut pk,
|
&mut pk,
|
||||||
|
@ -313,7 +313,7 @@ impl PublicKey {
|
||||||
secp: &Secp256k1<C>
|
secp: &Secp256k1<C>
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let res = ffi::secp256k1_ec_pubkey_negate(secp.ctx, &mut self.0 as *mut _);
|
let res = ffi::secp256k1_ec_pubkey_negate(secp.ctx, &mut self.0);
|
||||||
debug_assert_eq!(res, 1);
|
debug_assert_eq!(res, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,8 +331,7 @@ impl PublicKey {
|
||||||
return Err(Error::InvalidTweak);
|
return Err(Error::InvalidTweak);
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0 as *mut _,
|
if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0, other.as_c_ptr()) == 1 {
|
||||||
other.as_c_ptr()) == 1 {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidTweak)
|
Err(Error::InvalidTweak)
|
||||||
|
@ -353,8 +352,7 @@ impl PublicKey {
|
||||||
return Err(Error::InvalidTweak);
|
return Err(Error::InvalidTweak);
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0 as *mut _,
|
if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0, other.as_c_ptr()) == 1 {
|
||||||
other.as_c_ptr()) == 1 {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidTweak)
|
Err(Error::InvalidTweak)
|
||||||
|
|
17
src/lib.rs
17
src/lib.rs
|
@ -269,9 +269,8 @@ impl Signature {
|
||||||
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
|
||||||
if data.is_empty() {return Err(Error::InvalidSignature);}
|
if data.is_empty() {return Err(Error::InvalidSignature);}
|
||||||
|
|
||||||
let mut ret = ffi::Signature::new();
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut ret = ffi::Signature::new();
|
||||||
if ffi::secp256k1_ecdsa_signature_parse_der(
|
if ffi::secp256k1_ecdsa_signature_parse_der(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
|
@ -288,12 +287,12 @@ impl Signature {
|
||||||
|
|
||||||
/// Converts a 64-byte compact-encoded byte slice to a signature
|
/// Converts a 64-byte compact-encoded byte slice to a signature
|
||||||
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
|
||||||
let mut ret = ffi::Signature::new();
|
|
||||||
if data.len() != 64 {
|
if data.len() != 64 {
|
||||||
return Err(Error::InvalidSignature)
|
return Err(Error::InvalidSignature)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut ret = ffi::Signature::new();
|
||||||
if ffi::secp256k1_ecdsa_signature_parse_compact(
|
if ffi::secp256k1_ecdsa_signature_parse_compact(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
|
@ -362,13 +361,13 @@ impl Signature {
|
||||||
/// Obtains a raw pointer suitable for use with FFI functions
|
/// Obtains a raw pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_ptr(&self) -> *const ffi::Signature {
|
pub fn as_ptr(&self) -> *const ffi::Signature {
|
||||||
&self.0 as *const _
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature {
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature {
|
||||||
&mut self.0 as *mut _
|
&mut self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -522,6 +521,8 @@ pub enum Error {
|
||||||
InvalidRecoveryId,
|
InvalidRecoveryId,
|
||||||
/// Invalid tweak for add_*_assign or mul_*_assign
|
/// Invalid tweak for add_*_assign or mul_*_assign
|
||||||
InvalidTweak,
|
InvalidTweak,
|
||||||
|
/// `tweak_add_check` failed on an xonly public key
|
||||||
|
TweakCheckFailed,
|
||||||
/// Didn't pass enough memory to context creation with preallocated memory
|
/// Didn't pass enough memory to context creation with preallocated memory
|
||||||
NotEnoughMemory,
|
NotEnoughMemory,
|
||||||
}
|
}
|
||||||
|
@ -536,6 +537,7 @@ impl Error {
|
||||||
Error::InvalidSecretKey => "secp: malformed or out-of-range secret key",
|
Error::InvalidSecretKey => "secp: malformed or out-of-range secret key",
|
||||||
Error::InvalidRecoveryId => "secp: bad recovery id",
|
Error::InvalidRecoveryId => "secp: bad recovery id",
|
||||||
Error::InvalidTweak => "secp: bad tweak",
|
Error::InvalidTweak => "secp: bad tweak",
|
||||||
|
Error::TweakCheckFailed => "secp: xonly_pubkey_tewak_add_check failed",
|
||||||
Error::NotEnoughMemory => "secp: not enough memory allocated",
|
Error::NotEnoughMemory => "secp: not enough memory allocated",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -661,17 +663,16 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
pub fn sign(&self, msg: &Message, sk: &key::SecretKey)
|
pub fn sign(&self, msg: &Message, sk: &key::SecretKey)
|
||||||
-> Signature {
|
-> Signature {
|
||||||
|
|
||||||
let mut ret = ffi::Signature::new();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut ret = ffi::Signature::new();
|
||||||
// We can assume the return value because it's not possible to construct
|
// We can assume the return value because it's not possible to construct
|
||||||
// an invalid signature from a valid `Message` and `SecretKey`
|
// an invalid signature from a valid `Message` and `SecretKey`
|
||||||
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
|
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
|
||||||
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
|
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
|
||||||
ptr::null()), 1);
|
ptr::null()), 1);
|
||||||
}
|
|
||||||
|
|
||||||
Signature::from(ret)
|
Signature::from(ret)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates a random keypair. Convenience function for `key::SecretKey::new`
|
/// Generates a random keypair. Convenience function for `key::SecretKey::new`
|
||||||
/// and `key::PublicKey::from_secret_key`; call those functions directly for
|
/// and `key::PublicKey::from_secret_key`; call those functions directly for
|
||||||
|
|
|
@ -82,13 +82,13 @@ impl RecoverableSignature {
|
||||||
/// Obtains a raw pointer suitable for use with FFI functions
|
/// Obtains a raw pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_ptr(&self) -> *const ffi::RecoverableSignature {
|
pub fn as_ptr(&self) -> *const ffi::RecoverableSignature {
|
||||||
&self.0 as *const _
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature {
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature {
|
||||||
&mut self.0 as *mut _
|
&mut self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -112,17 +112,17 @@ impl RecoverableSignature {
|
||||||
/// for verification
|
/// for verification
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_standard(&self) -> Signature {
|
pub fn to_standard(&self) -> Signature {
|
||||||
let mut ret = super_ffi::Signature::new();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut ret = super_ffi::Signature::new();
|
||||||
let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(
|
let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(
|
||||||
super_ffi::secp256k1_context_no_precomp,
|
super_ffi::secp256k1_context_no_precomp,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
self.as_c_ptr(),
|
self.as_c_ptr(),
|
||||||
);
|
);
|
||||||
assert!(err == 1);
|
assert!(err == 1);
|
||||||
}
|
|
||||||
Signature(ret)
|
Signature(ret)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,16 +178,15 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
pub fn recover(&self, msg: &Message, sig: &RecoverableSignature)
|
pub fn recover(&self, msg: &Message, sig: &RecoverableSignature)
|
||||||
-> Result<key::PublicKey, Error> {
|
-> Result<key::PublicKey, Error> {
|
||||||
|
|
||||||
let mut pk = super_ffi::PublicKey::new();
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut pk = super_ffi::PublicKey::new();
|
||||||
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk,
|
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk,
|
||||||
sig.as_c_ptr(), msg.as_c_ptr()) != 1 {
|
sig.as_c_ptr(), msg.as_c_ptr()) != 1 {
|
||||||
return Err(Error::InvalidSignature);
|
return Err(Error::InvalidSignature);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
Ok(key::PublicKey::from(pk))
|
Ok(key::PublicKey::from(pk))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,13 +104,13 @@ impl KeyPair {
|
||||||
/// Obtains a raw const pointer suitable for use with FFI functions
|
/// Obtains a raw const pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_ptr(&self) -> *const ffi::KeyPair {
|
pub fn as_ptr(&self) -> *const ffi::KeyPair {
|
||||||
&self.0 as *const _
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut ffi::KeyPair {
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::KeyPair {
|
||||||
&mut self.0 as *mut _
|
&mut self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Schnorr KeyPair directly from a secret key slice
|
/// Creates a Schnorr KeyPair directly from a secret key slice
|
||||||
|
@ -123,8 +123,8 @@ impl KeyPair {
|
||||||
return Err(InvalidPublicKey);
|
return Err(InvalidPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut kp = ffi::KeyPair::new();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut kp = ffi::KeyPair::new();
|
||||||
if ffi::secp256k1_keypair_create(secp.ctx, &mut kp, data.as_c_ptr()) == 1 {
|
if ffi::secp256k1_keypair_create(secp.ctx, &mut kp, data.as_c_ptr()) == 1 {
|
||||||
Ok(KeyPair(kp))
|
Ok(KeyPair(kp))
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,21 +155,21 @@ impl KeyPair {
|
||||||
ret
|
ret
|
||||||
};
|
};
|
||||||
let mut data = random_32_bytes();
|
let mut data = random_32_bytes();
|
||||||
let mut keypair = ffi::KeyPair::new();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut keypair = ffi::KeyPair::new();
|
||||||
while ffi::secp256k1_keypair_create(secp.ctx, &mut keypair, data.as_c_ptr()) == 0 {
|
while ffi::secp256k1_keypair_create(secp.ctx, &mut keypair, data.as_c_ptr()) == 0 {
|
||||||
data = random_32_bytes();
|
data = random_32_bytes();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
KeyPair(keypair)
|
KeyPair(keypair)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Tweak a keypair by adding the given tweak to the secret key and updating the
|
/// Tweak a keypair by adding the given tweak to the secret key and updating the
|
||||||
/// public key accordingly.
|
/// public key accordingly.
|
||||||
/// Will return an error if the resulting key would be invalid or if
|
/// Will return an error if the resulting key would be invalid or if
|
||||||
/// the tweak was not a 32-byte length slice.
|
/// the tweak was not a 32-byte length slice.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add_assign<C: Verification>(
|
pub fn tweak_add_assign<C: Verification>(
|
||||||
&mut self,
|
&mut self,
|
||||||
secp: &Secp256k1<C>,
|
secp: &Secp256k1<C>,
|
||||||
tweak: &[u8],
|
tweak: &[u8],
|
||||||
|
@ -181,7 +181,7 @@ impl KeyPair {
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_keypair_xonly_tweak_add(
|
let err = ffi::secp256k1_keypair_xonly_tweak_add(
|
||||||
secp.ctx,
|
secp.ctx,
|
||||||
&mut self.0 as *mut _,
|
&mut self.0,
|
||||||
tweak.as_c_ptr(),
|
tweak.as_c_ptr(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -198,21 +198,21 @@ impl PublicKey {
|
||||||
/// Obtains a raw const pointer suitable for use with FFI functions
|
/// Obtains a raw const pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_ptr(&self) -> *const ffi::XOnlyPublicKey {
|
pub fn as_ptr(&self) -> *const ffi::XOnlyPublicKey {
|
||||||
&self.0 as *const _
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut ffi::XOnlyPublicKey {
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::XOnlyPublicKey {
|
||||||
&mut self.0 as *mut _
|
&mut self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new Schnorr public key from a Schnorr key pair
|
/// Creates a new Schnorr public key from a Schnorr key pair
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_keypair<C: Signing>(secp: &Secp256k1<C>, keypair: &KeyPair) -> PublicKey {
|
pub fn from_keypair<C: Signing>(secp: &Secp256k1<C>, keypair: &KeyPair) -> PublicKey {
|
||||||
let mut xonly_pk = ffi::XOnlyPublicKey::new();
|
|
||||||
let mut pk_parity = 0;
|
let mut pk_parity = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut xonly_pk = ffi::XOnlyPublicKey::new();
|
||||||
let ret = ffi::secp256k1_keypair_xonly_pub(
|
let ret = ffi::secp256k1_keypair_xonly_pub(
|
||||||
secp.ctx,
|
secp.ctx,
|
||||||
&mut xonly_pk,
|
&mut xonly_pk,
|
||||||
|
@ -220,9 +220,9 @@ impl PublicKey {
|
||||||
keypair.as_ptr(),
|
keypair.as_ptr(),
|
||||||
);
|
);
|
||||||
debug_assert_eq!(ret, 1);
|
debug_assert_eq!(ret, 1);
|
||||||
}
|
|
||||||
PublicKey(xonly_pk)
|
PublicKey(xonly_pk)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a Schnorr public key directly from a slice
|
/// Creates a Schnorr public key directly from a slice
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -231,8 +231,8 @@ impl PublicKey {
|
||||||
return Err(InvalidPublicKey);
|
return Err(InvalidPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pk = ffi::XOnlyPublicKey::new();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut pk = ffi::XOnlyPublicKey::new();
|
||||||
if ffi::secp256k1_xonly_pubkey_parse(
|
if ffi::secp256k1_xonly_pubkey_parse(
|
||||||
ffi::secp256k1_context_no_precomp,
|
ffi::secp256k1_context_no_precomp,
|
||||||
&mut pk,
|
&mut pk,
|
||||||
|
@ -264,14 +264,17 @@ impl PublicKey {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tweak a schnorrsig PublicKey by adding the generator multiplied with the given tweak to it.
|
/// Tweak an x-only PublicKey by adding the generator multiplied with the given tweak to it.
|
||||||
/// Will return an error if the resulting key would be invalid or if
|
///
|
||||||
/// the tweak was not a 32-byte length slice.
|
/// Returns a boolean representing the parity of the tweaked key, which can be provided to
|
||||||
pub fn add_assign<V: Verification>(
|
/// `tweak_add_check` which can be used to verify a tweak more efficiently than regenerating
|
||||||
|
/// it and checking equality. Will return an error if the resulting key would be invalid or
|
||||||
|
/// if the tweak was not a 32-byte length slice.
|
||||||
|
pub fn tweak_add_assign<V: Verification>(
|
||||||
&mut self,
|
&mut self,
|
||||||
secp: &Secp256k1<V>,
|
secp: &Secp256k1<V>,
|
||||||
tweak: &[u8],
|
tweak: &[u8],
|
||||||
) -> Result<(), Error> {
|
) -> Result<bool, Error> {
|
||||||
if tweak.len() != 32 {
|
if tweak.len() != 32 {
|
||||||
return Err(Error::InvalidTweak);
|
return Err(Error::InvalidTweak);
|
||||||
}
|
}
|
||||||
|
@ -289,18 +292,49 @@ impl PublicKey {
|
||||||
return Err(Error::InvalidTweak);
|
return Err(Error::InvalidTweak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut parity: ::secp256k1_sys::types::c_int = 0;
|
||||||
err = ffi::secp256k1_xonly_pubkey_from_pubkey(
|
err = ffi::secp256k1_xonly_pubkey_from_pubkey(
|
||||||
secp.ctx,
|
secp.ctx,
|
||||||
&mut self.0 as *mut _,
|
&mut self.0,
|
||||||
ptr::null_mut(),
|
&mut parity,
|
||||||
&pubkey,
|
&pubkey,
|
||||||
);
|
);
|
||||||
|
|
||||||
return if err == 0 {
|
if err == 0 {
|
||||||
Err(Error::InvalidPublicKey)
|
Err(Error::InvalidPublicKey)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(parity != 0)
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify that a tweak produced by `tweak_add_assign` was computed correctly
|
||||||
|
///
|
||||||
|
/// Should be called on the original untweaked key. Takes the tweaked key and
|
||||||
|
/// output parity from `tweak_add_assign` as input.
|
||||||
|
///
|
||||||
|
/// Currently this is not much more efficient than just recomputing the tweak
|
||||||
|
/// and checking equality. However, in future this API will support batch
|
||||||
|
/// verification, which is significantly faster, so it is wise to design
|
||||||
|
/// protocols with this in mind.
|
||||||
|
pub fn tweak_add_check<V: Verification>(
|
||||||
|
&self,
|
||||||
|
secp: &Secp256k1<V>,
|
||||||
|
tweaked_key: &Self,
|
||||||
|
tweaked_parity: bool,
|
||||||
|
tweak: [u8; 32],
|
||||||
|
) -> bool {
|
||||||
|
let tweaked_ser = tweaked_key.serialize();
|
||||||
|
unsafe {
|
||||||
|
let err = ffi::secp256k1_xonly_pubkey_tweak_add_check(
|
||||||
|
secp.ctx,
|
||||||
|
tweaked_ser.as_c_ptr(),
|
||||||
|
if tweaked_parity { 1 } else { 0 },
|
||||||
|
&self.0,
|
||||||
|
tweak.as_c_ptr(),
|
||||||
|
);
|
||||||
|
|
||||||
|
err == 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,9 +360,8 @@ impl From<ffi::XOnlyPublicKey> for PublicKey {
|
||||||
|
|
||||||
impl From<::key::PublicKey> for PublicKey {
|
impl From<::key::PublicKey> for PublicKey {
|
||||||
fn from(src: ::key::PublicKey) -> PublicKey {
|
fn from(src: ::key::PublicKey) -> PublicKey {
|
||||||
let mut pk = ffi::XOnlyPublicKey::new();
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut pk = ffi::XOnlyPublicKey::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1,
|
1,
|
||||||
ffi::secp256k1_xonly_pubkey_from_pubkey(
|
ffi::secp256k1_xonly_pubkey_from_pubkey(
|
||||||
|
@ -338,10 +371,9 @@ impl From<::key::PublicKey> for PublicKey {
|
||||||
src.as_c_ptr(),
|
src.as_c_ptr(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
PublicKey(pk)
|
PublicKey(pk)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_impl_from_slice!(PublicKey);
|
serde_impl_from_slice!(PublicKey);
|
||||||
|
@ -722,9 +754,11 @@ mod tests {
|
||||||
let mut tweak = [0u8; 32];
|
let mut tweak = [0u8; 32];
|
||||||
thread_rng().fill_bytes(&mut tweak);
|
thread_rng().fill_bytes(&mut tweak);
|
||||||
let (mut kp, mut pk) = s.generate_schnorrsig_keypair(&mut thread_rng());
|
let (mut kp, mut pk) = s.generate_schnorrsig_keypair(&mut thread_rng());
|
||||||
kp.add_assign(&s, &tweak).expect("Tweak error");
|
let orig_pk = pk;
|
||||||
pk.add_assign(&s, &tweak).expect("Tweak error");
|
kp.tweak_add_assign(&s, &tweak).expect("Tweak error");
|
||||||
|
let parity = pk.tweak_add_assign(&s, &tweak).expect("Tweak error");
|
||||||
assert_eq!(PublicKey::from_keypair(&s, &kp), pk);
|
assert_eq!(PublicKey::from_keypair(&s, &kp), pk);
|
||||||
|
assert!(orig_pk.tweak_add_check(&s, &pk, parity, tweak));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue