@@ -292,6 +292,31 @@ impl SecretKey {
292
292
pub fn sign_ecdsa ( & self , msg : Message ) -> ecdsa:: Signature {
293
293
SECP256K1 . sign_ecdsa ( & msg, self )
294
294
}
295
+
296
+ /// Returns the [`KeyPair`] for this [`SecretKey`].
297
+ ///
298
+ /// This is equivalent to using [`KeyPair::from_secret_key`].
299
+ #[ inline]
300
+ pub fn keypair < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> KeyPair {
301
+ KeyPair :: from_secret_key ( secp, self )
302
+ }
303
+
304
+ /// Returns the [`PublicKey`] for this [`SecretKey`].
305
+ ///
306
+ /// This is equivalent to using [`PublicKey::from_secret_key`].
307
+ #[ inline]
308
+ pub fn public_key < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> PublicKey {
309
+ PublicKey :: from_secret_key ( secp, self )
310
+ }
311
+
312
+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for this [`SecretKey`].
313
+ ///
314
+ /// This is equivalent to `XOnlyPublicKey::from_keypair(self.keypair(secp))`.
315
+ #[ inline]
316
+ pub fn x_only_public_key < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> ( XOnlyPublicKey , Parity ) {
317
+ let kp = self . keypair ( secp) ;
318
+ XOnlyPublicKey :: from_keypair ( & kp)
319
+ }
295
320
}
296
321
297
322
#[ cfg( feature = "serde" ) ]
@@ -418,6 +443,20 @@ impl PublicKey {
418
443
}
419
444
}
420
445
446
+ /// Creates a [`PublicKey`] using the key material from `pk` combined with the `parity`.
447
+ pub fn from_x_only_public_key ( pk : XOnlyPublicKey , parity : Parity ) -> PublicKey {
448
+ let mut buf = [ 0u8 ; 33 ] ;
449
+
450
+ // First byte of a compressed key should be `0x02 AND parity`.
451
+ buf[ 0 ] = match parity {
452
+ Parity :: Even => 0x02 ,
453
+ Parity :: Odd => 0x03 ,
454
+ } ;
455
+ buf[ 1 ..] . clone_from_slice ( & pk. serialize ( ) ) ;
456
+
457
+ PublicKey :: from_slice ( & buf) . expect ( "we know the buffer is valid" )
458
+ }
459
+
421
460
#[ inline]
422
461
/// Serializes the key as a byte-encoded pair of values. In compressed form the y-coordinate is
423
462
/// represented by only a single bit, as x determines it up to one bit.
@@ -589,6 +628,25 @@ impl PublicKey {
589
628
}
590
629
}
591
630
}
631
+
632
+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for this [`PublicKey`].
633
+ #[ inline]
634
+ pub fn x_only_public_key ( & self ) -> ( XOnlyPublicKey , Parity ) {
635
+ let mut pk_parity = 0 ;
636
+ unsafe {
637
+ let mut xonly_pk = ffi:: XOnlyPublicKey :: new ( ) ;
638
+ let ret = ffi:: secp256k1_xonly_pubkey_from_pubkey (
639
+ ffi:: secp256k1_context_no_precomp,
640
+ & mut xonly_pk,
641
+ & mut pk_parity,
642
+ self . as_ptr ( ) ,
643
+ ) ;
644
+ debug_assert_eq ! ( ret, 1 ) ;
645
+ let parity = Parity :: from_i32 ( pk_parity) . expect ( "should not panic, pk_parity is 0 or 1" ) ;
646
+
647
+ ( XOnlyPublicKey ( xonly_pk) , parity)
648
+ }
649
+ }
592
650
}
593
651
594
652
impl CPtr for PublicKey {
@@ -674,7 +732,7 @@ impl Ord for PublicKey {
674
732
///
675
733
/// let secp = Secp256k1::new();
676
734
/// let (secret_key, public_key) = secp.generate_keypair(&mut rand::thread_rng());
677
- /// let key_pair = KeyPair::from_secret_key(&secp, secret_key);
735
+ /// let key_pair = KeyPair::from_secret_key(&secp, & secret_key);
678
736
/// # }
679
737
/// ```
680
738
/// [`Deserialize`]: serde::Deserialize
@@ -700,7 +758,7 @@ impl KeyPair {
700
758
#[ inline]
701
759
pub fn from_secret_key < C : Signing > (
702
760
secp : & Secp256k1 < C > ,
703
- sk : SecretKey ,
761
+ sk : & SecretKey ,
704
762
) -> KeyPair {
705
763
unsafe {
706
764
let mut kp = ffi:: KeyPair :: new ( ) ;
@@ -860,9 +918,27 @@ impl KeyPair {
860
918
}
861
919
}
862
920
863
- /// Gets the [XOnlyPublicKey] for this [KeyPair].
921
+ /// Returns the [`SecretKey`] for this [`KeyPair`].
922
+ ///
923
+ /// This is equivalent to using [`SecretKey::from_keypair`].
924
+ #[ inline]
925
+ pub fn secret_key ( & self ) -> SecretKey {
926
+ SecretKey :: from_keypair ( self )
927
+ }
928
+
929
+ /// Returns the [`PublicKey`] for this [`KeyPair`].
930
+ ///
931
+ /// This is equivalent to using [`PublicKey::from_keypair`].
932
+ #[ inline]
933
+ pub fn public_key ( & self ) -> PublicKey {
934
+ PublicKey :: from_keypair ( self )
935
+ }
936
+
937
+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for this [`KeyPair`].
938
+ ///
939
+ /// This is equivalent to using [`XOnlyPublicKey::from_keypair`].
864
940
#[ inline]
865
- pub fn public_key ( & self ) -> XOnlyPublicKey {
941
+ pub fn x_only_public_key ( & self ) -> ( XOnlyPublicKey , Parity ) {
866
942
XOnlyPublicKey :: from_keypair ( self )
867
943
}
868
944
@@ -1008,9 +1084,9 @@ impl XOnlyPublicKey {
1008
1084
& mut self . 0
1009
1085
}
1010
1086
1011
- /// Creates a new Schnorr public key from a Schnorr key pair .
1087
+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for `keypair` .
1012
1088
#[ inline]
1013
- pub fn from_keypair ( keypair : & KeyPair ) -> XOnlyPublicKey {
1089
+ pub fn from_keypair ( keypair : & KeyPair ) -> ( XOnlyPublicKey , Parity ) {
1014
1090
let mut pk_parity = 0 ;
1015
1091
unsafe {
1016
1092
let mut xonly_pk = ffi:: XOnlyPublicKey :: new ( ) ;
@@ -1021,7 +1097,9 @@ impl XOnlyPublicKey {
1021
1097
keypair. as_ptr ( ) ,
1022
1098
) ;
1023
1099
debug_assert_eq ! ( ret, 1 ) ;
1024
- XOnlyPublicKey ( xonly_pk)
1100
+ let parity = Parity :: from_i32 ( pk_parity) . expect ( "should not panic, pk_parity is 0 or 1" ) ;
1101
+
1102
+ ( XOnlyPublicKey ( xonly_pk) , parity)
1025
1103
}
1026
1104
}
1027
1105
@@ -1092,7 +1170,7 @@ impl XOnlyPublicKey {
1092
1170
/// thread_rng().fill_bytes(&mut tweak);
1093
1171
///
1094
1172
/// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
1095
- /// let mut public_key = key_pair.public_key ();
1173
+ /// let ( mut public_key, _parity) = key_pair.x_only_public_key ();
1096
1174
/// public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
1097
1175
/// # }
1098
1176
/// ```
@@ -1105,6 +1183,7 @@ impl XOnlyPublicKey {
1105
1183
return Err ( Error :: InvalidTweak ) ;
1106
1184
}
1107
1185
1186
+ let mut pk_parity = 0 ;
1108
1187
unsafe {
1109
1188
let mut pubkey = ffi:: PublicKey :: new ( ) ;
1110
1189
let mut err = ffi:: secp256k1_xonly_pubkey_tweak_add (
@@ -1117,18 +1196,17 @@ impl XOnlyPublicKey {
1117
1196
return Err ( Error :: InvalidTweak ) ;
1118
1197
}
1119
1198
1120
- let mut parity: :: secp256k1_sys:: types:: c_int = 0 ;
1121
1199
err = ffi:: secp256k1_xonly_pubkey_from_pubkey (
1122
1200
secp. ctx ,
1123
1201
& mut self . 0 ,
1124
- & mut parity ,
1202
+ & mut pk_parity ,
1125
1203
& pubkey,
1126
1204
) ;
1127
1205
if err == 0 {
1128
1206
return Err ( Error :: InvalidPublicKey ) ;
1129
1207
}
1130
1208
1131
- Parity :: from_i32 ( parity ) . map_err ( Into :: into)
1209
+ Parity :: from_i32 ( pk_parity ) . map_err ( Into :: into)
1132
1210
}
1133
1211
}
1134
1212
@@ -1157,7 +1235,7 @@ impl XOnlyPublicKey {
1157
1235
/// thread_rng().fill_bytes(&mut tweak);
1158
1236
///
1159
1237
/// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
1160
- /// let mut public_key = key_pair.public_key ();
1238
+ /// let ( mut public_key, _) = key_pair.x_only_public_key ();
1161
1239
/// let original = public_key;
1162
1240
/// let parity = public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
1163
1241
/// assert!(original.tweak_add_check(&secp, &public_key, parity, tweak));
@@ -1183,6 +1261,14 @@ impl XOnlyPublicKey {
1183
1261
err == 1
1184
1262
}
1185
1263
}
1264
+
1265
+ /// Returns the [`PublicKey`] for this [`XOnlyPublicKey`].
1266
+ ///
1267
+ /// This is equivalent to using [`PublicKey::from_xonly_and_parity(self, parity)`].
1268
+ #[ inline]
1269
+ pub fn public_key ( & self , parity : Parity ) -> PublicKey {
1270
+ PublicKey :: from_x_only_public_key ( * self , parity)
1271
+ }
1186
1272
}
1187
1273
1188
1274
/// Represents the parity passed between FFI function calls.
@@ -1420,7 +1506,7 @@ pub mod serde_keypair {
1420
1506
1421
1507
Ok ( KeyPair :: from_secret_key (
1422
1508
& :: SECP256K1 ,
1423
- secret_key,
1509
+ & secret_key,
1424
1510
) )
1425
1511
}
1426
1512
}
@@ -1972,12 +2058,15 @@ mod test {
1972
2058
thread_rng ( ) . fill_bytes ( & mut tweak) ;
1973
2059
1974
2060
let mut kp = KeyPair :: new ( & s, & mut thread_rng ( ) ) ;
1975
- let mut pk = kp. public_key ( ) ;
2061
+ let ( mut pk, _parity ) = kp. x_only_public_key ( ) ;
1976
2062
1977
2063
let orig_pk = pk;
1978
2064
kp. tweak_add_assign ( & s, & tweak) . expect ( "Tweak error" ) ;
1979
2065
let parity = pk. tweak_add_assign ( & s, & tweak) . expect ( "Tweak error" ) ;
1980
- assert_eq ! ( XOnlyPublicKey :: from_keypair( & kp) , pk) ;
2066
+
2067
+ let ( back, _) = XOnlyPublicKey :: from_keypair ( & kp) ;
2068
+
2069
+ assert_eq ! ( back, pk) ;
1981
2070
assert ! ( orig_pk. tweak_add_check( & s, & pk, parity, tweak) ) ;
1982
2071
}
1983
2072
}
@@ -2046,4 +2135,150 @@ mod test {
2046
2135
assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
2047
2136
assert_tokens ( & sk. readable ( ) , & [ Token :: String ( SK_STR ) ] ) ;
2048
2137
}
2138
+
2139
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2140
+ fn keys ( ) -> ( SecretKey , PublicKey , KeyPair , XOnlyPublicKey ) {
2141
+ let secp = Secp256k1 :: new ( ) ;
2142
+
2143
+ static SK_BYTES : [ u8 ; 32 ] = [
2144
+ 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 ,
2145
+ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
2146
+ 0xff , 0xff , 0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 ,
2147
+ 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 ,
2148
+ ] ;
2149
+
2150
+ static PK_BYTES : [ u8 ; 32 ] = [
2151
+ 0x18 , 0x84 , 0x57 , 0x81 , 0xf6 , 0x31 , 0xc4 , 0x8f ,
2152
+ 0x1c , 0x97 , 0x09 , 0xe2 , 0x30 , 0x92 , 0x06 , 0x7d ,
2153
+ 0x06 , 0x83 , 0x7f , 0x30 , 0xaa , 0x0c , 0xd0 , 0x54 ,
2154
+ 0x4a , 0xc8 , 0x87 , 0xfe , 0x91 , 0xdd , 0xd1 , 0x66
2155
+ ] ;
2156
+
2157
+ let mut pk_bytes = [ 0u8 ; 33 ] ;
2158
+ pk_bytes[ 0 ] = 0x02 ; // Use positive Y co-ordinate.
2159
+ pk_bytes[ 1 ..] . clone_from_slice ( & PK_BYTES ) ;
2160
+
2161
+ let sk = SecretKey :: from_slice ( & SK_BYTES ) . expect ( "failed to parse sk bytes" ) ;
2162
+ let pk = PublicKey :: from_slice ( & pk_bytes) . expect ( "failed to create pk from iterator" ) ;
2163
+ let kp = KeyPair :: from_secret_key ( & secp, & sk) ;
2164
+ let xonly = XOnlyPublicKey :: from_slice ( & PK_BYTES ) . expect ( "failed to get xonly from slice" ) ;
2165
+
2166
+ ( sk, pk, kp, xonly)
2167
+ }
2168
+
2169
+ #[ test]
2170
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2171
+ fn convert_public_key_to_xonly_public_key ( ) {
2172
+ let ( _sk, pk, _kp, want) = keys ( ) ;
2173
+ let ( got, parity) = pk. x_only_public_key ( ) ;
2174
+
2175
+ assert_eq ! ( parity, Parity :: Even ) ;
2176
+ assert_eq ! ( got, want)
2177
+ }
2178
+
2179
+ #[ test]
2180
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2181
+ fn convert_secret_key_to_public_key ( ) {
2182
+ let secp = Secp256k1 :: new ( ) ;
2183
+
2184
+ let ( sk, want, _kp, _xonly) = keys ( ) ;
2185
+ let got = sk. public_key ( & secp) ;
2186
+
2187
+ assert_eq ! ( got, want)
2188
+ }
2189
+
2190
+ #[ test]
2191
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2192
+ fn convert_secret_key_to_x_only_public_key ( ) {
2193
+ let secp = Secp256k1 :: new ( ) ;
2194
+
2195
+ let ( sk, _pk, _kp, want) = keys ( ) ;
2196
+ let ( got, parity) = sk. x_only_public_key ( & secp) ;
2197
+
2198
+ assert_eq ! ( parity, Parity :: Even ) ;
2199
+ assert_eq ! ( got, want)
2200
+ }
2201
+
2202
+ #[ test]
2203
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2204
+ fn convert_keypair_to_public_key ( ) {
2205
+ let ( _sk, want, kp, _xonly) = keys ( ) ;
2206
+ let got = kp. public_key ( ) ;
2207
+
2208
+ assert_eq ! ( got, want)
2209
+ }
2210
+
2211
+ #[ test]
2212
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2213
+ fn convert_keypair_to_x_only_public_key ( ) {
2214
+ let ( _sk, _pk, kp, want) = keys ( ) ;
2215
+ let ( got, parity) = kp. x_only_public_key ( ) ;
2216
+
2217
+ assert_eq ! ( parity, Parity :: Even ) ;
2218
+ assert_eq ! ( got, want)
2219
+ }
2220
+
2221
+ // SecretKey -> KeyPair -> SecretKey
2222
+ #[ test]
2223
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2224
+ fn roundtrip_secret_key_via_keypair ( ) {
2225
+ let secp = Secp256k1 :: new ( ) ;
2226
+ let ( sk, _pk, _kp, _xonly) = keys ( ) ;
2227
+
2228
+ let kp = sk. keypair ( & secp) ;
2229
+ let back = kp. secret_key ( ) ;
2230
+
2231
+ assert_eq ! ( back, sk)
2232
+ }
2233
+
2234
+ // KeyPair -> SecretKey -> KeyPair
2235
+ #[ test]
2236
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2237
+ fn roundtrip_keypair_via_secret_key ( ) {
2238
+ let secp = Secp256k1 :: new ( ) ;
2239
+ let ( _sk, _pk, kp, _xonly) = keys ( ) ;
2240
+
2241
+ let sk = kp. secret_key ( ) ;
2242
+ let back = sk. keypair ( & secp) ;
2243
+
2244
+ assert_eq ! ( back, kp)
2245
+ }
2246
+
2247
+ // XOnlyPublicKey -> PublicKey -> XOnlyPublicKey
2248
+ #[ test]
2249
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2250
+ fn roundtrip_x_only_public_key_via_public_key ( ) {
2251
+ let ( _sk, _pk, _kp, xonly) = keys ( ) ;
2252
+
2253
+ let pk = xonly. public_key ( Parity :: Even ) ;
2254
+ let ( back, parity) = pk. x_only_public_key ( ) ;
2255
+
2256
+ assert_eq ! ( parity, Parity :: Even ) ;
2257
+ assert_eq ! ( back, xonly)
2258
+ }
2259
+
2260
+ // PublicKey -> XOnlyPublicKey -> PublicKey
2261
+ #[ test]
2262
+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2263
+ fn roundtrip_public_key_via_x_only_public_key ( ) {
2264
+ let ( _sk, pk, _kp, _xonly) = keys ( ) ;
2265
+
2266
+ let ( xonly, parity) = pk. x_only_public_key ( ) ;
2267
+ let back = xonly. public_key ( parity) ;
2268
+
2269
+ assert_eq ! ( back, pk)
2270
+ }
2271
+
2272
+ #[ test]
2273
+ fn public_key_from_x_only_public_key_and_odd_parity ( ) {
2274
+ let s = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166" ;
2275
+ let mut want = String :: from ( "03" ) ;
2276
+ want. push_str ( s) ;
2277
+
2278
+ let xonly = XOnlyPublicKey :: from_str ( s) . expect ( "failed to parse xonly pubkey string" ) ;
2279
+ let pk = xonly. public_key ( Parity :: Odd ) ;
2280
+ let got = format ! ( "{}" , pk) ;
2281
+
2282
+ assert_eq ! ( got, want)
2283
+ }
2049
2284
}
0 commit comments