@@ -13,26 +13,46 @@ use crate::ffi::recovery as ffi;
1313use crate :: { key, Error , Message , Secp256k1 , Signing , Verification } ;
1414
1515/// A tag used for recovering the public key from a compact signature.
16- #[ derive( Copy , Clone , PartialEq , Eq , Debug , Ord , PartialOrd ) ]
17- pub struct RecoveryId ( i32 ) ;
16+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
17+ pub enum RecoveryId {
18+ /// Signature recovery ID 0
19+ Zero ,
20+ /// Signature recovery ID 1
21+ One ,
22+ /// Signature recovery ID 2
23+ Two ,
24+ /// Signature recovery ID 3
25+ Three ,
26+ }
1827
1928/// An ECDSA signature with a recovery ID for pubkey recovery.
2029#[ derive( Copy , Clone , PartialEq , Eq , Debug , Hash , Ord , PartialOrd ) ]
2130pub struct RecoverableSignature ( ffi:: RecoverableSignature ) ;
2231
23- impl RecoveryId {
32+ impl TryFrom < i32 > for RecoveryId {
33+ type Error = Error ;
2434 #[ inline]
25- /// Allows library users to create valid recovery IDs from i32.
26- pub fn from_i32 ( id : i32 ) -> Result < RecoveryId , Error > {
35+ fn try_from ( id : i32 ) -> Result < RecoveryId , Error > {
2736 match id {
28- 0 ..=3 => Ok ( RecoveryId ( id) ) ,
37+ 0 => Ok ( RecoveryId :: Zero ) ,
38+ 1 => Ok ( RecoveryId :: One ) ,
39+ 2 => Ok ( RecoveryId :: Two ) ,
40+ 3 => Ok ( RecoveryId :: Three ) ,
2941 _ => Err ( Error :: InvalidRecoveryId ) ,
3042 }
3143 }
44+ }
3245
46+ impl Into < i32 > for RecoveryId {
3347 #[ inline]
34- /// Allows library users to convert recovery IDs to i32.
35- pub fn to_i32 ( self ) -> i32 { self . 0 }
48+ fn into ( self ) -> i32 {
49+ match self {
50+ RecoveryId :: Zero => 0 ,
51+ RecoveryId :: One => 1 ,
52+ RecoveryId :: Two => 2 ,
53+ RecoveryId :: Three => 3 ,
54+ }
55+ }
3656}
3757
3858impl RecoverableSignature {
@@ -53,7 +73,7 @@ impl RecoverableSignature {
5373 super_ffi:: secp256k1_context_no_precomp,
5474 & mut ret,
5575 data. as_c_ptr ( ) ,
56- recid. 0 ,
76+ recid. into ( ) ,
5777 ) == 1
5878 {
5979 Ok ( RecoverableSignature ( ret) )
@@ -80,7 +100,7 @@ impl RecoverableSignature {
80100 /// Serializes the recoverable signature in compact format.
81101 pub fn serialize_compact ( & self ) -> ( RecoveryId , [ u8 ; 64 ] ) {
82102 let mut ret = [ 0u8 ; 64 ] ;
83- let mut recid = 0i32 ;
103+ let mut recid = RecoveryId :: Zero . into ( ) ;
84104 unsafe {
85105 let err = ffi:: secp256k1_ecdsa_recoverable_signature_serialize_compact (
86106 super_ffi:: secp256k1_context_no_precomp,
@@ -90,7 +110,7 @@ impl RecoverableSignature {
90110 ) ;
91111 assert ! ( err == 1 ) ;
92112 }
93- ( RecoveryId ( recid) , ret)
113+ ( recid. try_into ( ) . expect ( "ffi returned invalid RecoveryId!" ) , ret)
94114 }
95115
96116 /// Converts a recoverable signature to a non-recoverable one (this is needed
@@ -245,7 +265,7 @@ mod tests {
245265
246266 #[ test]
247267 fn recid_sanity_check ( ) {
248- let one = RecoveryId ( 1 ) ;
268+ let one = RecoveryId :: One ;
249269 assert_eq ! ( one, one. clone( ) ) ;
250270 }
251271
@@ -271,7 +291,7 @@ mod tests {
271291 0x80 , 0x12 , 0x0e , 0xf8 , 0x02 , 0x5e , 0x70 , 0x9f ,
272292 0xff , 0x20 , 0x80 , 0xc4 , 0xa3 , 0x9a , 0xae , 0x06 ,
273293 0x8d , 0x12 , 0xee , 0xd0 , 0x09 , 0xb6 , 0x8c , 0x89 ] ,
274- RecoveryId ( 1 ) ) )
294+ RecoveryId :: One ) )
275295 }
276296
277297 #[ test]
@@ -297,7 +317,7 @@ mod tests {
297317 0xd9 , 0xfd , 0xdb , 0x44 , 0xbd , 0x0d , 0xd9 , 0xb9 ,
298318 0xdd , 0x47 , 0x66 , 0x6a , 0xb5 , 0x28 , 0x71 , 0x90 ,
299319 0x1d , 0x17 , 0x61 , 0xeb , 0x82 , 0xec , 0x87 , 0x22 ] ,
300- RecoveryId ( 0 ) ) )
320+ RecoveryId :: Zero ) )
301321 }
302322
303323 #[ test]
@@ -365,10 +385,10 @@ mod tests {
365385 let msg = Message :: from_digest_slice ( & [ 0x55 ; 32 ] ) . unwrap ( ) ;
366386
367387 // Zero is not a valid sig
368- let sig = RecoverableSignature :: from_compact ( & [ 0 ; 64 ] , RecoveryId ( 0 ) ) . unwrap ( ) ;
388+ let sig = RecoverableSignature :: from_compact ( & [ 0 ; 64 ] , RecoveryId :: Zero ) . unwrap ( ) ;
369389 assert_eq ! ( s. recover_ecdsa( & msg, & sig) , Err ( Error :: InvalidSignature ) ) ;
370390 // ...but 111..111 is
371- let sig = RecoverableSignature :: from_compact ( & [ 1 ; 64 ] , RecoveryId ( 0 ) ) . unwrap ( ) ;
391+ let sig = RecoverableSignature :: from_compact ( & [ 1 ; 64 ] , RecoveryId :: Zero ) . unwrap ( ) ;
372392 assert ! ( s. recover_ecdsa( & msg, & sig) . is_ok( ) ) ;
373393 }
374394
@@ -384,13 +404,13 @@ mod tests {
384404 0x80 , 0x12 , 0x0e , 0xf8 , 0x02 , 0x5e , 0x70 , 0x9f ,
385405 0xff , 0x20 , 0x80 , 0xc4 , 0xa3 , 0x9a , 0xae , 0x06 ,
386406 0x8d , 0x12 , 0xee , 0xd0 , 0x09 , 0xb6 , 0x8c , 0x89 ] ,
387- RecoveryId ( 1 ) ) . unwrap ( ) ;
407+ RecoveryId :: One ) . unwrap ( ) ;
388408 assert_eq ! ( & format!( "{:?}" , sig) , "RecoverableSignature(6673ffad2147741f04772b6f921f0ba6af0c1e77fc439e65c36dedf4092e88984c1a971652e0ada880120ef8025e709fff2080c4a39aae068d12eed009b68c8901)" ) ;
389409 }
390410
391411 #[ test]
392412 fn test_recov_sig_serialize_compact ( ) {
393- let recid_in = RecoveryId ( 1 ) ;
413+ let recid_in = RecoveryId :: One ;
394414 #[ rustfmt:: skip]
395415 let bytes_in = & [
396416 0x66 , 0x73 , 0xff , 0xad , 0x21 , 0x47 , 0x74 , 0x1f ,
@@ -409,16 +429,16 @@ mod tests {
409429
410430 #[ test]
411431 fn test_recov_id_conversion_between_i32 ( ) {
412- assert ! ( RecoveryId :: from_i32 ( - 1 ) . is_err( ) ) ;
413- assert ! ( RecoveryId :: from_i32 ( 0 ) . is_ok( ) ) ;
414- assert ! ( RecoveryId :: from_i32 ( 1 ) . is_ok( ) ) ;
415- assert ! ( RecoveryId :: from_i32 ( 2 ) . is_ok( ) ) ;
416- assert ! ( RecoveryId :: from_i32 ( 3 ) . is_ok( ) ) ;
417- assert ! ( RecoveryId :: from_i32 ( 4 ) . is_err( ) ) ;
418- let id0 = RecoveryId :: from_i32 ( 0 ) . unwrap ( ) ;
419- assert_eq ! ( id0 . to_i32 ( ) , 0 ) ;
420- let id1 = RecoveryId ( 1 ) ;
421- assert_eq ! ( id1 . to_i32 ( ) , 1 ) ;
432+ assert ! ( RecoveryId :: try_from ( - 1i32 ) . is_err( ) ) ;
433+ assert ! ( RecoveryId :: try_from ( 0i32 ) . is_ok( ) ) ;
434+ assert ! ( RecoveryId :: try_from ( 1i32 ) . is_ok( ) ) ;
435+ assert ! ( RecoveryId :: try_from ( 2i32 ) . is_ok( ) ) ;
436+ assert ! ( RecoveryId :: try_from ( 3i32 ) . is_ok( ) ) ;
437+ assert ! ( RecoveryId :: try_from ( 4i32 ) . is_err( ) ) ;
438+ let id0 = RecoveryId :: Zero ;
439+ assert_eq ! ( Into :: < i32 > :: into ( id0 ) , 0i32 ) ;
440+ let id1 = RecoveryId :: One ;
441+ assert_eq ! ( Into :: < i32 > :: into ( id1 ) , 1i32 ) ;
422442 }
423443}
424444
0 commit comments