@@ -13,11 +13,11 @@ use std;
13
13
14
14
use crate :: ffi:: { self , CPtr } ;
15
15
use crate :: {
16
- schnorr, Error , Keypair , Message , PublicKey , Scalar , Secp256k1 , SecretKey , Signing ,
16
+ from_hex , schnorr, Error , Keypair , Message , PublicKey , Scalar , Secp256k1 , SecretKey , Signing ,
17
17
Verification , XOnlyPublicKey ,
18
18
} ;
19
19
20
- /// Musig partial signature parsing errors
20
+ /// Musig parsing errors
21
21
#[ derive( Debug , Clone , Copy , Eq , PartialEq , PartialOrd , Ord , Hash ) ]
22
22
pub enum ParseError {
23
23
/// Parse Argument is malformed. This might occur if the point is on the secp order,
@@ -222,6 +222,62 @@ impl CPtr for PartialSignature {
222
222
fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target { self . as_mut_ptr ( ) }
223
223
}
224
224
225
+ impl fmt:: LowerHex for PartialSignature {
226
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
227
+ for b in self . serialize ( ) {
228
+ write ! ( f, "{:02x}" , b) ?;
229
+ }
230
+ Ok ( ( ) )
231
+ }
232
+ }
233
+
234
+ impl fmt:: Display for PartialSignature {
235
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result { fmt:: LowerHex :: fmt ( self , f) }
236
+ }
237
+
238
+ impl core:: str:: FromStr for PartialSignature {
239
+ type Err = ParseError ;
240
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
241
+ let mut res = [ 0u8 ; ffi:: MUSIG_PART_SIG_SERIALIZED_LEN ] ;
242
+ match from_hex ( s, & mut res) {
243
+ Ok ( ffi:: MUSIG_PART_SIG_SERIALIZED_LEN ) => PartialSignature :: from_byte_array ( & res) ,
244
+ _ => Err ( ParseError :: MalformedArg ) ,
245
+ }
246
+ }
247
+ }
248
+
249
+ #[ cfg( feature = "serde" ) ]
250
+ impl serde:: Serialize for PartialSignature {
251
+ fn serialize < S : serde:: Serializer > ( & self , s : S ) -> Result < S :: Ok , S :: Error > {
252
+ if s. is_human_readable ( ) {
253
+ s. collect_str ( self )
254
+ } else {
255
+ s. serialize_bytes ( & self . serialize ( ) [ ..] )
256
+ }
257
+ }
258
+ }
259
+
260
+ #[ cfg( feature = "serde" ) ]
261
+ impl < ' de > serde:: Deserialize < ' de > for PartialSignature {
262
+ fn deserialize < D : serde:: Deserializer < ' de > > ( d : D ) -> Result < Self , D :: Error > {
263
+ if d. is_human_readable ( ) {
264
+ d. deserialize_str ( super :: serde_util:: FromStrVisitor :: new (
265
+ "a hex string representing a MuSig2 partial signature" ,
266
+ ) )
267
+ } else {
268
+ d. deserialize_bytes ( super :: serde_util:: BytesVisitor :: new (
269
+ "a raw MuSig2 partial signature" ,
270
+ |slice| {
271
+ let bytes: & [ u8 ; ffi:: MUSIG_PART_SIG_SERIALIZED_LEN ] =
272
+ slice. try_into ( ) . map_err ( |_| ParseError :: MalformedArg ) ?;
273
+
274
+ Self :: from_byte_array ( bytes)
275
+ } ,
276
+ ) )
277
+ }
278
+ }
279
+ }
280
+
225
281
impl PartialSignature {
226
282
/// Serialize a PartialSignature as a byte array.
227
283
pub fn serialize ( & self ) -> [ u8 ; ffi:: MUSIG_PART_SIG_SERIALIZED_LEN ] {
@@ -635,6 +691,62 @@ impl CPtr for PublicNonce {
635
691
fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target { self . as_mut_ptr ( ) }
636
692
}
637
693
694
+ impl fmt:: LowerHex for PublicNonce {
695
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
696
+ for b in self . serialize ( ) {
697
+ write ! ( f, "{:02x}" , b) ?;
698
+ }
699
+ Ok ( ( ) )
700
+ }
701
+ }
702
+
703
+ impl fmt:: Display for PublicNonce {
704
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result { fmt:: LowerHex :: fmt ( self , f) }
705
+ }
706
+
707
+ impl core:: str:: FromStr for PublicNonce {
708
+ type Err = ParseError ;
709
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
710
+ let mut res = [ 0u8 ; ffi:: MUSIG_PUBNONCE_SERIALIZED_LEN ] ;
711
+ match from_hex ( s, & mut res) {
712
+ Ok ( ffi:: MUSIG_PUBNONCE_SERIALIZED_LEN ) => PublicNonce :: from_byte_array ( & res) ,
713
+ _ => Err ( ParseError :: MalformedArg ) ,
714
+ }
715
+ }
716
+ }
717
+
718
+ #[ cfg( feature = "serde" ) ]
719
+ impl serde:: Serialize for PublicNonce {
720
+ fn serialize < S : serde:: Serializer > ( & self , s : S ) -> Result < S :: Ok , S :: Error > {
721
+ if s. is_human_readable ( ) {
722
+ s. collect_str ( self )
723
+ } else {
724
+ s. serialize_bytes ( & self . serialize ( ) [ ..] )
725
+ }
726
+ }
727
+ }
728
+
729
+ #[ cfg( feature = "serde" ) ]
730
+ impl < ' de > serde:: Deserialize < ' de > for PublicNonce {
731
+ fn deserialize < D : serde:: Deserializer < ' de > > ( d : D ) -> Result < Self , D :: Error > {
732
+ if d. is_human_readable ( ) {
733
+ d. deserialize_str ( super :: serde_util:: FromStrVisitor :: new (
734
+ "a hex string representing a MuSig2 public nonce" ,
735
+ ) )
736
+ } else {
737
+ d. deserialize_bytes ( super :: serde_util:: BytesVisitor :: new (
738
+ "a raw MuSig2 public nonce" ,
739
+ |slice| {
740
+ let bytes: & [ u8 ; ffi:: MUSIG_PUBNONCE_SERIALIZED_LEN ] =
741
+ slice. try_into ( ) . map_err ( |_| ParseError :: MalformedArg ) ?;
742
+
743
+ Self :: from_byte_array ( bytes)
744
+ } ,
745
+ ) )
746
+ }
747
+ }
748
+ }
749
+
638
750
impl PublicNonce {
639
751
/// Serialize a PublicNonce
640
752
pub fn serialize ( & self ) -> [ u8 ; ffi:: MUSIG_PUBNONCE_SERIALIZED_LEN ] {
@@ -696,6 +808,62 @@ impl CPtr for AggregatedNonce {
696
808
fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target { self . as_mut_ptr ( ) }
697
809
}
698
810
811
+ impl fmt:: LowerHex for AggregatedNonce {
812
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
813
+ for b in self . serialize ( ) {
814
+ write ! ( f, "{:02x}" , b) ?;
815
+ }
816
+ Ok ( ( ) )
817
+ }
818
+ }
819
+
820
+ impl fmt:: Display for AggregatedNonce {
821
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result { fmt:: LowerHex :: fmt ( self , f) }
822
+ }
823
+
824
+ impl core:: str:: FromStr for AggregatedNonce {
825
+ type Err = ParseError ;
826
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
827
+ let mut res = [ 0u8 ; ffi:: MUSIG_AGGNONCE_SERIALIZED_LEN ] ;
828
+ match from_hex ( s, & mut res) {
829
+ Ok ( ffi:: MUSIG_AGGNONCE_SERIALIZED_LEN ) => AggregatedNonce :: from_byte_array ( & res) ,
830
+ _ => Err ( ParseError :: MalformedArg ) ,
831
+ }
832
+ }
833
+ }
834
+
835
+ #[ cfg( feature = "serde" ) ]
836
+ impl serde:: Serialize for AggregatedNonce {
837
+ fn serialize < S : serde:: Serializer > ( & self , s : S ) -> Result < S :: Ok , S :: Error > {
838
+ if s. is_human_readable ( ) {
839
+ s. collect_str ( self )
840
+ } else {
841
+ s. serialize_bytes ( & self . serialize ( ) [ ..] )
842
+ }
843
+ }
844
+ }
845
+
846
+ #[ cfg( feature = "serde" ) ]
847
+ impl < ' de > serde:: Deserialize < ' de > for AggregatedNonce {
848
+ fn deserialize < D : serde:: Deserializer < ' de > > ( d : D ) -> Result < Self , D :: Error > {
849
+ if d. is_human_readable ( ) {
850
+ d. deserialize_str ( super :: serde_util:: FromStrVisitor :: new (
851
+ "a hex string representing a MuSig2 aggregated nonce" ,
852
+ ) )
853
+ } else {
854
+ d. deserialize_bytes ( super :: serde_util:: BytesVisitor :: new (
855
+ "a raw MuSig2 aggregated nonce" ,
856
+ |slice| {
857
+ let bytes: & [ u8 ; ffi:: MUSIG_AGGNONCE_SERIALIZED_LEN ] =
858
+ slice. try_into ( ) . map_err ( |_| ParseError :: MalformedArg ) ?;
859
+
860
+ Self :: from_byte_array ( bytes)
861
+ } ,
862
+ ) )
863
+ }
864
+ }
865
+ }
866
+
699
867
impl AggregatedNonce {
700
868
/// Combine received public nonces into a single aggregated nonce
701
869
///
@@ -1520,4 +1688,21 @@ mod tests {
1520
1688
1521
1689
let _agg_sig = session. partial_sig_agg ( & [ ] ) ;
1522
1690
}
1691
+
1692
+ #[ test]
1693
+ fn de_serialization ( ) {
1694
+ const MUSIG_PUBLIC_NONCE_HEX : & str = "03f4a361abd3d50535be08421dbc73b0a8f595654ae3238afcaf2599f94e25204c036ba174214433e21f5cd0fcb14b038eb40b05b7e7c820dd21aa568fdb0a9de4d7" ;
1695
+ let pubnonce: PublicNonce = MUSIG_PUBLIC_NONCE_HEX . parse ( ) . unwrap ( ) ;
1696
+
1697
+ assert_eq ! ( pubnonce. to_string( ) , MUSIG_PUBLIC_NONCE_HEX ) ;
1698
+
1699
+ const MUSIG_AGGREGATED_NONCE_HEX : & str = "0218c30fe0f567a4a9c05eb4835e2735419cf30f834c9ce2fe3430f021ba4eacd503112e97bcf6a022d236d71a9357824a2b19515f980131b3970b087cadf94cc4a7" ;
1700
+ let aggregated_nonce: AggregatedNonce = MUSIG_AGGREGATED_NONCE_HEX . parse ( ) . unwrap ( ) ;
1701
+ assert_eq ! ( aggregated_nonce. to_string( ) , MUSIG_AGGREGATED_NONCE_HEX ) ;
1702
+
1703
+ const MUSIG_PARTIAL_SIGNATURE_HEX : & str =
1704
+ "289eeb2f5efc314aa6d87bf58125043c96d15a007db4b6aaaac7d18086f49a99" ;
1705
+ let partial_signature: PartialSignature = MUSIG_PARTIAL_SIGNATURE_HEX . parse ( ) . unwrap ( ) ;
1706
+ assert_eq ! ( partial_signature. to_string( ) , MUSIG_PARTIAL_SIGNATURE_HEX ) ;
1707
+ }
1523
1708
}
0 commit comments