From 389abddcc789da672071aa9ae452664aeecce9ec Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Wed, 12 Jan 2022 18:11:55 +1100 Subject: [PATCH 1/2] Add method KeyPair::public_key Currently to get the `XOnlyPublicKey` from a `KeyPair` users must do `XOnlyPublicKey::from_keypair(&kp)`. While this does the job we can make the lib more ergonomic by providing a method directly on `KeyPair` that calls through to `XOnlyPublicKey::from_keypair`. Add method `KeyPair::public_key(&self)`. --- src/key.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/key.rs b/src/key.rs index 8c0f0a0..09a4e49 100644 --- a/src/key.rs +++ b/src/key.rs @@ -650,6 +650,12 @@ impl KeyPair { Ok(()) } } + + /// Gets the [XOnlyPublicKey] for this [KeyPair]. + #[inline] + pub fn public_key(&self) -> XOnlyPublicKey { + XOnlyPublicKey::from_keypair(self) + } } impl From for SecretKey { From 97524b2da7885d74a7c15d23d9db22882b53f0f2 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Wed, 12 Jan 2022 18:01:02 +1100 Subject: [PATCH 2/2] Deprecate generate_schnorrsig_keypair We have deprecated all other functions that use the identifier 'schnorrsig' but we missed `generate_schnorrsig_keypair`. This function is purely a helper function and serves no real purpose other than to reduce two lines of code to a single line. Downstream users can write this function themselves if they need it. Also, we recently added a new public method to `KeyPair` to get the public key in a slightly more ergonomic fashion. Use `kp.public_key()` when replacing usage of now deprecated `generate_schnorrsig_keypair` function. --- src/key.rs | 5 ++++- src/schnorr.rs | 40 ++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/key.rs b/src/key.rs index 09a4e49..f8fdd99 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1553,7 +1553,10 @@ mod test { for _ in 0..10 { let mut tweak = [0u8; 32]; thread_rng().fill_bytes(&mut tweak); - let (mut kp, mut pk) = s.generate_schnorrsig_keypair(&mut thread_rng()); + + let mut kp = KeyPair::new(&s, &mut thread_rng()); + let mut pk = kp.public_key(); + let orig_pk = pk; kp.tweak_add_assign(&s, &tweak).expect("Tweak error"); let parity = pk.tweak_add_assign(&s, &tweak).expect("Tweak error"); diff --git a/src/schnorr.rs b/src/schnorr.rs index b5a77cd..e713913 100644 --- a/src/schnorr.rs +++ b/src/schnorr.rs @@ -248,15 +248,14 @@ impl Secp256k1 { } impl Secp256k1 { - - /// Generates a random Schnorr KeyPair and its associated Schnorr PublicKey. - /// Convenience function for `schnorrsig::KeyPair::new` and - /// `schnorrsig::PublicKey::from_keypair`; call those functions directly for - /// batch key generation. Requires a signing-capable context. Requires compilation - /// with the "rand" feature. + /// Generates a random Schnorr `KeyPair` and its associated Schnorr `XOnlyPublicKey`. + /// + /// Convenience function for [KeyPair::new] and [KeyPair::public_key]. + /// Requires a signing-capable context and requires compilation with the "rand" feature. #[inline] #[cfg(any(test, feature = "rand"))] #[cfg_attr(docsrs, doc(cfg(feature = "rand")))] + #[deprecated(since = "0.21.0", note = "Use kp = KeyPair::new() and kp.public_key()")] pub fn generate_schnorrsig_keypair( &self, rng: &mut R, @@ -325,16 +324,18 @@ mod tests { let secp = Secp256k1::new(); let mut rng = thread_rng(); - let (seckey, pubkey) = secp.generate_schnorrsig_keypair(&mut rng); + let kp = KeyPair::new(&secp, &mut rng); + let pk = kp.public_key(); + let mut msg = [0u8; 32]; for _ in 0..100 { rng.fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let sig = sign(&secp, &msg, &seckey, &mut rng); + let sig = sign(&secp, &msg, &kp, &mut rng); - assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok()); + assert!(secp.verify_schnorr(&sig, &msg, &pk).is_ok()); } } @@ -390,10 +391,12 @@ mod tests { #[test] fn test_pubkey_serialize_roundtrip() { let secp = Secp256k1::new(); - let (_, pubkey) = secp.generate_schnorrsig_keypair(&mut thread_rng()); - let ser = pubkey.serialize(); + let kp = KeyPair::new(&secp, &mut thread_rng()); + let pk = kp.public_key(); + + let ser = pk.serialize(); let pubkey2 = XOnlyPublicKey::from_slice(&ser).unwrap(); - assert_eq!(pubkey, pubkey2); + assert_eq!(pk, pubkey2); } #[test] @@ -405,7 +408,7 @@ mod tests { assert_eq!(SecretKey::from_str(sk_str).unwrap(), sk); let pk = ::key::PublicKey::from_keypair(&keypair); assert_eq!(::key::PublicKey::from_secret_key(&secp, &sk), pk); - let xpk = XOnlyPublicKey::from_keypair(&keypair); + let xpk = keypair.public_key(); assert_eq!(XOnlyPublicKey::from(pk), xpk); } @@ -445,12 +448,12 @@ mod tests { 0x63, 0x63, 0x63, 0x63, ]; - let sk = KeyPair::from_seckey_slice(&secp, &SK_BYTES).expect("sk"); + let kp = KeyPair::from_seckey_slice(&secp, &SK_BYTES).expect("sk"); // In fuzzing mode secret->public key derivation is different, so // hard-code the epected result. #[cfg(not(fuzzing))] - let pk = XOnlyPublicKey::from_keypair(&sk); + let pk = kp.public_key(); #[cfg(fuzzing)] let pk = XOnlyPublicKey::from_slice(&[0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66]).expect("pk"); @@ -512,10 +515,11 @@ mod tests { } } - let s = Secp256k1::new(); - let (_, pubkey) = s.generate_schnorrsig_keypair(&mut DumbRng(0)); + let secp = Secp256k1::new(); + let kp = KeyPair::new(&secp, &mut DumbRng(0)); + let pk = kp.public_key(); assert_eq!( - &pubkey.serialize()[..], + &pk.serialize()[..], &[ 124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9, 181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229