schnorrsig: expose tweak_check_add API
This commit is contained in:
parent
12b0abbcf8
commit
37049d743e
|
@ -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",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<C: Verification>(
|
||||
pub fn tweak_add_assign<C: Verification>(
|
||||
&mut self,
|
||||
secp: &Secp256k1<C>,
|
||||
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<V: Verification>(
|
||||
/// 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<V: Verification>(
|
||||
&mut self,
|
||||
secp: &Secp256k1<V>,
|
||||
tweak: &[u8],
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<bool, Error> {
|
||||
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<V: Verification>(
|
||||
&self,
|
||||
secp: &Secp256k1<V>,
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue