@@ -13,11 +13,11 @@ use std;
1313
1414use crate :: ffi:: { self , CPtr } ;
1515use crate :: {
16- schnorr, Error , Keypair , Message , PublicKey , Scalar , Secp256k1 , SecretKey , Signing ,
16+ from_hex , schnorr, Error , Keypair , Message , PublicKey , Scalar , Secp256k1 , SecretKey , Signing ,
1717 Verification , XOnlyPublicKey ,
1818} ;
1919
20- /// Musig partial signature parsing errors
20+ /// Musig parsing errors
2121#[ derive( Debug , Clone , Copy , Eq , PartialEq , PartialOrd , Ord , Hash ) ]
2222pub enum ParseError {
2323 /// Parse Argument is malformed. This might occur if the point is on the secp order,
@@ -222,6 +222,62 @@ impl CPtr for PartialSignature {
222222 fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target { self . as_mut_ptr ( ) }
223223}
224224
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+
225281impl PartialSignature {
226282 /// Serialize a PartialSignature as a byte array.
227283 pub fn serialize ( & self ) -> [ u8 ; ffi:: MUSIG_PART_SIG_SERIALIZED_LEN ] {
@@ -635,6 +691,62 @@ impl CPtr for PublicNonce {
635691 fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target { self . as_mut_ptr ( ) }
636692}
637693
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+
638750impl PublicNonce {
639751 /// Serialize a PublicNonce
640752 pub fn serialize ( & self ) -> [ u8 ; ffi:: MUSIG_PUBNONCE_SERIALIZED_LEN ] {
@@ -696,6 +808,62 @@ impl CPtr for AggregatedNonce {
696808 fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target { self . as_mut_ptr ( ) }
697809}
698810
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+
699867impl AggregatedNonce {
700868 /// Combine received public nonces into a single aggregated nonce
701869 ///
@@ -1520,4 +1688,21 @@ mod tests {
15201688
15211689 let _agg_sig = session. partial_sig_agg ( & [ ] ) ;
15221690 }
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+ }
15231708}
0 commit comments