Add opaque parity type

Two functions in the FFI secp code return and accept a parity int.
Currently we are manually converting this to a bool. Doing so forces
readers of the code to think what the bool means even though
understanding this bool is not needed since in is just passed back down
to the FFI code. We can abstract this away by using an opaque type to
hold the original int and not converting it to a boolean value.

Add 'Return' and 'Error' sections to `tweak_add_assign` while fixing the
docs to describe the new opaque parity type.
This commit is contained in:
Tobin Harding 2022-01-04 08:49:08 +11:00
parent 1b768b2749
commit fbc64c7725
1 changed files with 27 additions and 10 deletions

View File

@ -824,15 +824,18 @@ impl XOnlyPublicKey {
/// Tweak an x-only 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.
/// ///
/// Returns a boolean representing the parity of the tweaked key, which can be provided to /// # Return
/// An opaque type representing the parity of the tweaked key, this should be provided to
/// `tweak_add_check` which can be used to verify a tweak more efficiently than regenerating /// `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 /// it and checking equality.
/// if the tweak was not a 32-byte length slice. ///
/// # 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>( pub fn tweak_add_assign<V: Verification>(
&mut self, &mut self,
secp: &Secp256k1<V>, secp: &Secp256k1<V>,
tweak: &[u8], tweak: &[u8],
) -> Result<bool, Error> { ) -> Result<Parity, Error> {
if tweak.len() != 32 { if tweak.len() != 32 {
return Err(Error::InvalidTweak); return Err(Error::InvalidTweak);
} }
@ -856,12 +859,11 @@ impl XOnlyPublicKey {
&mut parity, &mut parity,
&pubkey, &pubkey,
); );
if err == 0 { if err == 0 {
Err(Error::InvalidPublicKey) return Err(Error::InvalidPublicKey);
} else {
Ok(parity != 0)
} }
Ok(parity.into())
} }
} }
@ -878,7 +880,7 @@ impl XOnlyPublicKey {
&self, &self,
secp: &Secp256k1<V>, secp: &Secp256k1<V>,
tweaked_key: &Self, tweaked_key: &Self,
tweaked_parity: bool, tweaked_parity: Parity,
tweak: [u8; 32], tweak: [u8; 32],
) -> bool { ) -> bool {
let tweaked_ser = tweaked_key.serialize(); let tweaked_ser = tweaked_key.serialize();
@ -886,7 +888,7 @@ impl XOnlyPublicKey {
let err = ffi::secp256k1_xonly_pubkey_tweak_add_check( let err = ffi::secp256k1_xonly_pubkey_tweak_add_check(
secp.ctx, secp.ctx,
tweaked_ser.as_c_ptr(), tweaked_ser.as_c_ptr(),
if tweaked_parity { 1 } else { 0 }, tweaked_parity.into(),
&self.0, &self.0,
tweak.as_c_ptr(), tweak.as_c_ptr(),
); );
@ -896,6 +898,21 @@ impl XOnlyPublicKey {
} }
} }
/// Opaque type used to hold the parity passed between FFI function calls.
pub struct Parity(i32);
impl From<i32> for Parity {
fn from(parity: i32) -> Parity {
Parity(parity)
}
}
impl From<Parity> for i32 {
fn from(parity: Parity) -> i32 {
parity.0
}
}
impl CPtr for XOnlyPublicKey { impl CPtr for XOnlyPublicKey {
type Target = ffi::XOnlyPublicKey; type Target = ffi::XOnlyPublicKey;
fn as_c_ptr(&self) -> *const Self::Target { fn as_c_ptr(&self) -> *const Self::Target {