From fbc64c77252e86100a657fa3d381b36c22eeb48e Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 4 Jan 2022 08:49:08 +1100 Subject: [PATCH] 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. --- src/key.rs | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/key.rs b/src/key.rs index 04a1522..791b63b 100644 --- a/src/key.rs +++ b/src/key.rs @@ -824,15 +824,18 @@ impl XOnlyPublicKey { /// 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 - /// 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. + /// it and checking equality. + /// + /// # 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 { + ) -> Result { if tweak.len() != 32 { return Err(Error::InvalidTweak); } @@ -856,12 +859,11 @@ impl XOnlyPublicKey { &mut parity, &pubkey, ); - if err == 0 { - Err(Error::InvalidPublicKey) - } else { - Ok(parity != 0) + return Err(Error::InvalidPublicKey); } + + Ok(parity.into()) } } @@ -878,7 +880,7 @@ impl XOnlyPublicKey { &self, secp: &Secp256k1, tweaked_key: &Self, - tweaked_parity: bool, + tweaked_parity: Parity, tweak: [u8; 32], ) -> bool { let tweaked_ser = tweaked_key.serialize(); @@ -886,7 +888,7 @@ impl XOnlyPublicKey { let err = ffi::secp256k1_xonly_pubkey_tweak_add_check( secp.ctx, tweaked_ser.as_c_ptr(), - if tweaked_parity { 1 } else { 0 }, + tweaked_parity.into(), &self.0, 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 for Parity { + fn from(parity: i32) -> Parity { + Parity(parity) + } +} + +impl From for i32 { + fn from(parity: Parity) -> i32 { + parity.0 + } +} + impl CPtr for XOnlyPublicKey { type Target = ffi::XOnlyPublicKey; fn as_c_ptr(&self) -> *const Self::Target {