From 12b0abbcf835341a9e842a7d8c88c51a9c8c1354 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Fri, 27 Nov 2020 17:49:11 +0000 Subject: [PATCH 1/4] make `ffi::Type::new` functions all unsafe, expand documentation --- secp256k1-sys/src/lib.rs | 130 ++++++++++++++++++++++++++++++--------- src/key.rs | 6 +- src/lib.rs | 10 ++- src/recovery.rs | 11 ++-- src/schnorrsig.rs | 18 +++--- 5 files changed, 120 insertions(+), 55 deletions(-) diff --git a/secp256k1-sys/src/lib.rs b/secp256k1-sys/src/lib.rs index b3979edf7..2b413b632 100644 --- a/secp256k1-sys/src/lib.rs +++ b/secp256k1-sys/src/lib.rs @@ -106,13 +106,32 @@ impl_array_newtype!(PublicKey, c_uchar, 64); impl_raw_debug!(PublicKey); impl PublicKey { - /// Create a new (zeroed) public key usable for the FFI interface - pub fn new() -> PublicKey { PublicKey([0; 64]) } -} + /// Creates an "uninitialized" FFI public key which is zeroed out + /// + /// 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 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 { + PublicKey(data) + } -impl Default for PublicKey { - fn default() -> Self { - PublicKey::new() + /// 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 Signature { - /// Create a new (zeroed) signature usable for the FFI interface - pub fn new() -> Signature { Signature([0; 64]) } -} + /// Creates an "uninitialized" FFI signature which is zeroed out + /// + /// 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 { - fn default() -> Self { - Signature::new() + /// Create a new signature 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 { + 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 XOnlyPublicKey { - /// Create a new (zeroed) x-only public key usable for the FFI interface - pub fn new() -> XOnlyPublicKey { XOnlyPublicKey([0; 64]) } - pub fn from_array(data: [c_uchar; 64]) -> XOnlyPublicKey { + /// Creates an "uninitialized" FFI x-only public key which is zeroed out + /// + /// 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) } + + /// 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 { @@ -158,23 +218,39 @@ impl hash::Hash for XOnlyPublicKey { } } -impl Default for XOnlyPublicKey { - fn default() -> Self { - XOnlyPublicKey::new() - } -} - #[repr(C)] pub struct KeyPair([c_uchar; 96]); impl_array_newtype!(KeyPair, c_uchar, 96); impl_raw_debug!(KeyPair); impl KeyPair { - /// Create a new (zeroed) key pair usable for the FFI interface - pub fn new() -> KeyPair { KeyPair([0; 96]) } - pub fn from_array(data: [c_uchar; 96]) -> KeyPair { + /// Creates an "uninitialized" FFI keypair which is zeroed out + /// + /// 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) } + + /// 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 { @@ -183,12 +259,6 @@ impl hash::Hash for KeyPair { } } -impl Default for KeyPair { - fn default() -> Self { - KeyPair::new() - } -} - #[cfg(not(feature = "fuzztarget"))] extern "C" { /// Default ECDH hash function diff --git a/src/key.rs b/src/key.rs index a9ee114b7..49a7a2b2c 100644 --- a/src/key.rs +++ b/src/key.rs @@ -233,14 +233,14 @@ impl PublicKey { pub fn from_secret_key(secp: &Secp256k1, sk: &SecretKey) -> PublicKey { - let mut pk = ffi::PublicKey::new(); unsafe { + let mut pk = ffi::PublicKey::new(); // We can assume the return value because it's not possible to construct // an invalid `SecretKey` without transmute trickery or something let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_c_ptr()); debug_assert_eq!(res, 1); + PublicKey(pk) } - PublicKey(pk) } /// Creates a public key directly from a slice @@ -248,8 +248,8 @@ impl PublicKey { pub fn from_slice(data: &[u8]) -> Result { if data.is_empty() {return Err(Error::InvalidPublicKey);} - let mut pk = ffi::PublicKey::new(); unsafe { + let mut pk = ffi::PublicKey::new(); if ffi::secp256k1_ec_pubkey_parse( ffi::secp256k1_context_no_precomp, &mut pk, diff --git a/src/lib.rs b/src/lib.rs index 79fa82c48..d1878a3cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -269,9 +269,8 @@ impl Signature { pub fn from_der(data: &[u8]) -> Result { if data.is_empty() {return Err(Error::InvalidSignature);} - let mut ret = ffi::Signature::new(); - unsafe { + let mut ret = ffi::Signature::new(); if ffi::secp256k1_ecdsa_signature_parse_der( ffi::secp256k1_context_no_precomp, &mut ret, @@ -288,12 +287,12 @@ impl Signature { /// Converts a 64-byte compact-encoded byte slice to a signature pub fn from_compact(data: &[u8]) -> Result { - let mut ret = ffi::Signature::new(); if data.len() != 64 { return Err(Error::InvalidSignature) } unsafe { + let mut ret = ffi::Signature::new(); if ffi::secp256k1_ecdsa_signature_parse_compact( ffi::secp256k1_context_no_precomp, &mut ret, @@ -661,16 +660,15 @@ impl Secp256k1 { pub fn sign(&self, msg: &Message, sk: &key::SecretKey) -> Signature { - let mut ret = ffi::Signature::new(); unsafe { + let mut ret = ffi::Signature::new(); // We can assume the return value because it's not possible to construct // an invalid signature from a valid `Message` and `SecretKey` assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(), sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979, ptr::null()), 1); + Signature::from(ret) } - - Signature::from(ret) } /// Generates a random keypair. Convenience function for `key::SecretKey::new` diff --git a/src/recovery.rs b/src/recovery.rs index 015299419..94532dfd8 100644 --- a/src/recovery.rs +++ b/src/recovery.rs @@ -112,16 +112,16 @@ impl RecoverableSignature { /// for verification #[inline] pub fn to_standard(&self) -> Signature { - let mut ret = super_ffi::Signature::new(); unsafe { + let mut ret = super_ffi::Signature::new(); let err = ffi::secp256k1_ecdsa_recoverable_signature_convert( super_ffi::secp256k1_context_no_precomp, &mut ret, self.as_c_ptr(), ); assert!(err == 1); + Signature(ret) } - Signature(ret) } } @@ -178,15 +178,14 @@ impl Secp256k1 { pub fn recover(&self, msg: &Message, sig: &RecoverableSignature) -> Result { - let mut pk = super_ffi::PublicKey::new(); - unsafe { + let mut pk = super_ffi::PublicKey::new(); if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, sig.as_c_ptr(), msg.as_c_ptr()) != 1 { return Err(Error::InvalidSignature); } - }; - Ok(key::PublicKey::from(pk)) + Ok(key::PublicKey::from(pk)) + } } } diff --git a/src/schnorrsig.rs b/src/schnorrsig.rs index eec559456..5a01a523e 100644 --- a/src/schnorrsig.rs +++ b/src/schnorrsig.rs @@ -123,8 +123,8 @@ impl KeyPair { return Err(InvalidPublicKey); } - let mut kp = ffi::KeyPair::new(); unsafe { + let mut kp = ffi::KeyPair::new(); if ffi::secp256k1_keypair_create(secp.ctx, &mut kp, data.as_c_ptr()) == 1 { Ok(KeyPair(kp)) } else { @@ -155,13 +155,13 @@ impl KeyPair { ret }; let mut data = random_32_bytes(); - let mut keypair = ffi::KeyPair::new(); unsafe { + let mut keypair = ffi::KeyPair::new(); while ffi::secp256k1_keypair_create(secp.ctx, &mut keypair, data.as_c_ptr()) == 0 { data = random_32_bytes(); } + KeyPair(keypair) } - KeyPair(keypair) } /// Tweak a keypair by adding the given tweak to the secret key and updating the @@ -210,9 +210,9 @@ impl PublicKey { /// Creates a new Schnorr public key from a Schnorr key pair #[inline] pub fn from_keypair(secp: &Secp256k1, keypair: &KeyPair) -> PublicKey { - let mut xonly_pk = ffi::XOnlyPublicKey::new(); let mut pk_parity = 0; unsafe { + let mut xonly_pk = ffi::XOnlyPublicKey::new(); let ret = ffi::secp256k1_keypair_xonly_pub( secp.ctx, &mut xonly_pk, @@ -220,8 +220,8 @@ impl PublicKey { keypair.as_ptr(), ); debug_assert_eq!(ret, 1); + PublicKey(xonly_pk) } - PublicKey(xonly_pk) } /// Creates a Schnorr public key directly from a slice @@ -231,8 +231,8 @@ impl PublicKey { return Err(InvalidPublicKey); } - let mut pk = ffi::XOnlyPublicKey::new(); unsafe { + let mut pk = ffi::XOnlyPublicKey::new(); if ffi::secp256k1_xonly_pubkey_parse( ffi::secp256k1_context_no_precomp, &mut pk, @@ -326,9 +326,8 @@ impl From for PublicKey { impl From<::key::PublicKey> for PublicKey { fn from(src: ::key::PublicKey) -> PublicKey { - let mut pk = ffi::XOnlyPublicKey::new(); - unsafe { + let mut pk = ffi::XOnlyPublicKey::new(); assert_eq!( 1, ffi::secp256k1_xonly_pubkey_from_pubkey( @@ -338,9 +337,8 @@ impl From<::key::PublicKey> for PublicKey { src.as_c_ptr(), ) ); + PublicKey(pk) } - - PublicKey(pk) } } From 37049d743e67935d7968db30ab0e62bedf97ca13 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Fri, 27 Nov 2020 18:31:00 +0000 Subject: [PATCH 2/4] schnorrsig: expose tweak_check_add API --- src/lib.rs | 3 +++ src/schnorrsig.rs | 66 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d1878a3cc..43a3b1d17 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -521,6 +521,8 @@ pub enum Error { InvalidRecoveryId, /// Invalid tweak for add_*_assign or mul_*_assign InvalidTweak, + /// `tweak_add_check` failed on an xonly public key + TweakCheckFailed, /// Didn't pass enough memory to context creation with preallocated memory NotEnoughMemory, } @@ -535,6 +537,7 @@ impl Error { Error::InvalidSecretKey => "secp: malformed or out-of-range secret key", Error::InvalidRecoveryId => "secp: bad recovery id", Error::InvalidTweak => "secp: bad tweak", + Error::TweakCheckFailed => "secp: xonly_pubkey_tewak_add_check failed", Error::NotEnoughMemory => "secp: not enough memory allocated", } } diff --git a/src/schnorrsig.rs b/src/schnorrsig.rs index 5a01a523e..d76f9b2d2 100644 --- a/src/schnorrsig.rs +++ b/src/schnorrsig.rs @@ -169,7 +169,7 @@ impl KeyPair { /// Will return an error if the resulting key would be invalid or if /// the tweak was not a 32-byte length slice. #[inline] - pub fn add_assign( + pub fn tweak_add_assign( &mut self, secp: &Secp256k1, tweak: &[u8], @@ -264,14 +264,17 @@ impl PublicKey { ret } - /// Tweak a schnorrsig 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. - pub fn add_assign( + /// Tweak an x-only PublicKey by adding the generator multiplied with the given tweak to it. + /// + /// Returns a boolean representing the parity of the tweaked key, which can be provided to + /// `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( &mut self, secp: &Secp256k1, tweak: &[u8], - ) -> Result<(), Error> { + ) -> Result { if tweak.len() != 32 { return Err(Error::InvalidTweak); } @@ -289,18 +292,57 @@ impl PublicKey { return Err(Error::InvalidTweak); } + let mut parity: ::secp256k1_sys::types::c_int = 0; err = ffi::secp256k1_xonly_pubkey_from_pubkey( secp.ctx, &mut self.0 as *mut _, - ptr::null_mut(), + &mut parity as *mut _, &pubkey, ); - return if err == 0 { + if err == 0 { Err(Error::InvalidPublicKey) } else { + 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( + &self, + secp: &Secp256k1, + tweaked_key: &Self, + tweaked_parity: bool, + tweak: &[u8], + ) -> Result<(), Error> { + if tweak.len() != 32 { + return Err(Error::InvalidTweak); + } + + 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 as *const _, + tweak.as_c_ptr(), + ); + + if err == 1 { Ok(()) - }; + } else { + Err(Error::TweakCheckFailed) + } } } } @@ -720,9 +762,11 @@ mod tests { let mut tweak = [0u8; 32]; thread_rng().fill_bytes(&mut tweak); let (mut kp, mut pk) = s.generate_schnorrsig_keypair(&mut thread_rng()); - kp.add_assign(&s, &tweak).expect("Tweak error"); - pk.add_assign(&s, &tweak).expect("Tweak error"); + let orig_pk = pk; + 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); + orig_pk.tweak_add_check(&s, &pk, parity, &tweak).expect("tweak check"); } } From 0ec8fab82c667d52e9f6a10fb6a9f09607a521fa Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Mon, 30 Nov 2020 02:47:34 +0000 Subject: [PATCH 3/4] stop explicitly casting references to rawptrs --- secp256k1-sys/src/lib.rs | 2 +- src/key.rs | 12 +++++------- src/lib.rs | 4 ++-- src/recovery.rs | 4 ++-- src/schnorrsig.rs | 16 ++++++++-------- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/secp256k1-sys/src/lib.rs b/secp256k1-sys/src/lib.rs index 2b413b632..27de54481 100644 --- a/secp256k1-sys/src/lib.rs +++ b/secp256k1-sys/src/lib.rs @@ -661,7 +661,7 @@ impl CPtr for [T] { fn as_mut_c_ptr(&mut self) -> *mut Self::Target { if self.is_empty() { - ptr::null::() as *mut _ + ptr::null_mut::() } else { self.as_mut_ptr() } diff --git a/src/key.rs b/src/key.rs index 49a7a2b2c..bbed29949 100644 --- a/src/key.rs +++ b/src/key.rs @@ -219,13 +219,13 @@ impl PublicKey { /// Obtains a raw const pointer suitable for use with FFI functions #[inline] 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 #[inline] 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. @@ -313,7 +313,7 @@ impl PublicKey { secp: &Secp256k1 ) { 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); } } @@ -331,8 +331,7 @@ impl PublicKey { return Err(Error::InvalidTweak); } unsafe { - if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0 as *mut _, - other.as_c_ptr()) == 1 { + if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0, other.as_c_ptr()) == 1 { Ok(()) } else { Err(Error::InvalidTweak) @@ -353,8 +352,7 @@ impl PublicKey { return Err(Error::InvalidTweak); } unsafe { - if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0 as *mut _, - other.as_c_ptr()) == 1 { + if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0, other.as_c_ptr()) == 1 { Ok(()) } else { Err(Error::InvalidTweak) diff --git a/src/lib.rs b/src/lib.rs index 43a3b1d17..483ddd9dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -361,13 +361,13 @@ impl Signature { /// Obtains a raw pointer suitable for use with FFI functions #[inline] 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 #[inline] pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature { - &mut self.0 as *mut _ + &mut self.0 } #[inline] diff --git a/src/recovery.rs b/src/recovery.rs index 94532dfd8..9c4a554e5 100644 --- a/src/recovery.rs +++ b/src/recovery.rs @@ -82,13 +82,13 @@ impl RecoverableSignature { /// Obtains a raw pointer suitable for use with FFI functions #[inline] 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 #[inline] pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature { - &mut self.0 as *mut _ + &mut self.0 } #[inline] diff --git a/src/schnorrsig.rs b/src/schnorrsig.rs index d76f9b2d2..e9324f55e 100644 --- a/src/schnorrsig.rs +++ b/src/schnorrsig.rs @@ -104,13 +104,13 @@ impl KeyPair { /// Obtains a raw const pointer suitable for use with FFI functions #[inline] 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 #[inline] 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 @@ -181,7 +181,7 @@ impl KeyPair { unsafe { let err = ffi::secp256k1_keypair_xonly_tweak_add( secp.ctx, - &mut self.0 as *mut _, + &mut self.0, tweak.as_c_ptr(), ); @@ -198,13 +198,13 @@ impl PublicKey { /// Obtains a raw const pointer suitable for use with FFI functions #[inline] 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 #[inline] 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 @@ -295,8 +295,8 @@ impl PublicKey { let mut parity: ::secp256k1_sys::types::c_int = 0; err = ffi::secp256k1_xonly_pubkey_from_pubkey( secp.ctx, - &mut self.0 as *mut _, - &mut parity as *mut _, + &mut self.0, + &mut parity, &pubkey, ); @@ -334,7 +334,7 @@ impl PublicKey { secp.ctx, tweaked_ser.as_c_ptr(), if tweaked_parity { 1 } else { 0 }, - &self.0 as *const _, + &self.0, tweak.as_c_ptr(), ); From ea027ce258ca9b7078b1808f66221417a52ff82d Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 9 Dec 2020 16:49:48 +0000 Subject: [PATCH 4/4] schnorrsig: change tweak_add_check to return a bool, take a fixed-length array --- src/schnorrsig.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/schnorrsig.rs b/src/schnorrsig.rs index e9324f55e..858a1d550 100644 --- a/src/schnorrsig.rs +++ b/src/schnorrsig.rs @@ -322,12 +322,8 @@ impl PublicKey { secp: &Secp256k1, tweaked_key: &Self, tweaked_parity: bool, - tweak: &[u8], - ) -> Result<(), Error> { - if tweak.len() != 32 { - return Err(Error::InvalidTweak); - } - + tweak: [u8; 32], + ) -> bool { let tweaked_ser = tweaked_key.serialize(); unsafe { let err = ffi::secp256k1_xonly_pubkey_tweak_add_check( @@ -338,11 +334,7 @@ impl PublicKey { tweak.as_c_ptr(), ); - if err == 1 { - Ok(()) - } else { - Err(Error::TweakCheckFailed) - } + err == 1 } } } @@ -766,7 +758,7 @@ mod tests { 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); - orig_pk.tweak_add_check(&s, &pk, parity, &tweak).expect("tweak check"); + assert!(orig_pk.tweak_add_check(&s, &pk, parity, tweak)); } }