11use std:: fmt:: { Debug , Formatter } ;
22
33use anyhow:: Context ;
4+ use mithril_stm:: AggregateSignatureType ;
45use serde:: { Deserialize , Serialize } ;
56
67use crate :: StdError ;
@@ -270,7 +271,7 @@ impl TryFrom<Certificate> for CertificateMessage {
270271 let ( multi_signature, genesis_signature) = match certificate. signature {
271272 CertificateSignature :: GenesisSignature ( signature) => (
272273 String :: new ( ) ,
273- signature . to_bytes_hex ( ) . with_context ( || {
274+ String :: try_from ( & signature ) . with_context ( || {
274275 "Can not convert certificate to message: can not encode the genesis signature"
275276 } ) ?,
276277 ) ,
@@ -279,17 +280,31 @@ impl TryFrom<Certificate> for CertificateMessage {
279280 genesis_schnorr_signature = hex:: encode ( schnorr_signature. to_bytes ( ) ) ;
280281 (
281282 String :: new ( ) ,
282- ed_signature . to_bytes_hex ( ) . with_context ( || {
283+ String :: try_from ( & ed_signature ) . with_context ( || {
283284 "Can not convert certificate to message: can not encode the genesis signature"
284285 } ) ?,
285286 )
286287 }
287- CertificateSignature :: MultiSignature ( _, signature) => (
288- signature. to_json_hex ( ) . with_context ( || {
288+ CertificateSignature :: MultiSignature ( _, signature) => {
289+ // Temporary workaround: encode the multi-signature per aggregate signature type
290+ // instead of natively through the ProtocolKey codec (`String::try_from(&signature)`).
291+ // The bytes encoding of an aggregate signature is only decodable by clients from
292+ // distribution 2617.0 onwards, so concatenation multi-signatures must stay JSON-hex
293+ // until the older distributions (up to 2603.1) are retired. Once they are, register
294+ // `AggregateSignature` under `bytes_hex_codec` and replace this match with
295+ // `String::try_from(&signature)`.
296+ let encoded_multi_signature = match AggregateSignatureType :: from ( & * signature) {
297+ AggregateSignatureType :: Concatenation => signature. to_json_hex ( ) ,
298+ #[ cfg( feature = "future_snark" ) ]
299+ AggregateSignatureType :: Snark | AggregateSignatureType :: IvcSnark => {
300+ signature. to_bytes_hex ( )
301+ }
302+ }
303+ . with_context ( || {
289304 "Can not convert certificate to message: can not encode the multi-signature"
290- } ) ?,
291- String :: new ( ) ,
292- ) ,
305+ } ) ?;
306+ ( encoded_multi_signature , String :: new ( ) )
307+ }
293308 } ;
294309
295310 let message = CertificateMessage {
@@ -694,4 +709,45 @@ mod tests {
694709 }
695710 }
696711 }
712+
713+ mod multi_signature_encoding {
714+ use crate :: test:: double:: fake_data;
715+
716+ use super :: * ;
717+
718+ #[ test]
719+ fn concatenation_multi_signature_is_encoded_as_json_hex ( ) {
720+ let certificate = fake_data:: certificate ( "hash" ) ;
721+ let expected_json_hex = match & certificate. signature {
722+ CertificateSignature :: MultiSignature ( _, signature) => {
723+ signature. to_json_hex ( ) . unwrap ( )
724+ }
725+ _ => panic ! ( "expected a multi-signature certificate" ) ,
726+ } ;
727+
728+ let message = CertificateMessage :: try_from ( certificate) . unwrap ( ) ;
729+
730+ assert_eq ! ( expected_json_hex, message. multi_signature) ;
731+ }
732+
733+ #[ cfg( feature = "future_snark" ) ]
734+ #[ test]
735+ fn snark_multi_signature_is_encoded_as_bytes_hex ( ) {
736+ let snark_signature = fake_data:: snark_aggregate_signature ( ) ;
737+ let expected_bytes_hex = snark_signature. to_bytes_hex ( ) . unwrap ( ) ;
738+ let mut certificate = fake_data:: certificate ( "hash" ) ;
739+ let signed_entity_type = match & certificate. signature {
740+ CertificateSignature :: MultiSignature ( signed_entity_type, _) => {
741+ signed_entity_type. clone ( )
742+ }
743+ _ => panic ! ( "expected a multi-signature certificate" ) ,
744+ } ;
745+ certificate. signature =
746+ CertificateSignature :: MultiSignature ( signed_entity_type, snark_signature) ;
747+
748+ let message = CertificateMessage :: try_from ( certificate) . unwrap ( ) ;
749+
750+ assert_eq ! ( expected_bytes_hex, message. multi_signature) ;
751+ }
752+ }
697753}
0 commit comments