Skip to content

Commit 6981ddd

Browse files
committed
feat(common): encode SNARK aggregate signature as bytes
Encode the multi-signature by type: JSON-hex for concatenation (backward compatible), bytes-hex for SNARK and IVC proofs.
1 parent 8bbdf2d commit 6981ddd

1 file changed

Lines changed: 63 additions & 7 deletions

File tree

mithril-common/src/messages/certificate.rs

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fmt::{Debug, Formatter};
22

33
use anyhow::Context;
4+
use mithril_stm::AggregateSignatureType;
45
use serde::{Deserialize, Serialize};
56

67
use 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

Comments
 (0)