From 6019e21661bf3f16be74c902820779dec24e901b Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Thu, 29 Aug 2024 17:53:23 +0200 Subject: [PATCH 1/6] Add `signed_message` prop to `RegisterSingleSignatureMessage` in openapi --- openapi.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openapi.yaml b/openapi.yaml index e61184065ca..54dbb9e35d8 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -1068,12 +1068,21 @@ components: items: type: integer format: int64 + signed_message: + description: | + Hash of the protocol message that is signed by the signer + + Optional, allow the aggregator to store this signature for later if it has yet to start to work + on the message. + type: string + format: bytes example: { "entity_type": { "MithrilStakeDistribution": 246 }, "party_id": "1234567890", "signature": "7b2c36322c3130352c3232322c31302c3131302c33312c37312c39372c22766b223a5b3136342c2c31393137352c313834", - "indexes": [25, 35] + "indexes": [25, 35], + "signed_message": "07ed7c9e128744c1a4797b7eb34c54823cc7a21fc95c19876122ab4bb0fe796d6bba2bc" } ProtocolMessageParts: From eb4270c3a49463f935c0db22956ad4f7f05ca4bf Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:18:36 +0200 Subject: [PATCH 2/6] Add signed message to `RegisterSignatureMessage` in common --- .../src/messages/register_signature.rs | 58 +++++++++++++++---- .../to_register_signature_message.rs | 1 + .../src/stress_test/payload_builder.rs | 1 + 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/mithril-common/src/messages/register_signature.rs b/mithril-common/src/messages/register_signature.rs index e1ea47ec817..e74f744192e 100644 --- a/mithril-common/src/messages/register_signature.rs +++ b/mithril-common/src/messages/register_signature.rs @@ -21,6 +21,13 @@ pub struct RegisterSignatureMessage { /// The indexes of the won lotteries that lead to the single signatures #[serde(rename = "indexes")] pub won_indexes: Vec, + + /// Message that is signed by the signer + /// + /// Used to buffer the signature for later if the Aggregator has yet to create an open message + /// for the signed entity type. + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_message: Option, } impl RegisterSignatureMessage { @@ -32,6 +39,7 @@ impl RegisterSignatureMessage { party_id: "party_id".to_string(), signature: fake_keys::single_signature()[0].to_string(), won_indexes: vec![1, 3], + signed_message: None, } } } @@ -62,28 +70,58 @@ mod tests { use super::*; - fn golden_message() -> RegisterSignatureMessage { + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] + pub struct RegisterSignatureMessagePrevious { + #[serde(rename = "entity_type")] + pub signed_entity_type: SignedEntityType, + pub party_id: PartyId, + pub signature: HexEncodedSingleSignature, + #[serde(rename = "indexes")] + pub won_indexes: Vec, + } + + fn golden_message_previous() -> RegisterSignatureMessagePrevious { + RegisterSignatureMessagePrevious { + signed_entity_type: SignedEntityType::MithrilStakeDistribution(Epoch(246)), + party_id: "party_id".to_string(), + signature: "7b227369676d61223a5b3133302c3137372c31352c3232392c32342c3235312c3234372c3137312c3139362c3231302c3134332c3131332c38362c3138392c39322c35362c3131322c33332c3139332c3231322c35342c3231342c32382c3231362c3232372c3137332c3130302c3132372c3137382c34302c39382c38372c32392c3138312c3235352c3131312c3135372c3232342c3233352c34362c3130302c3136392c3233322c3138392c3235322c38322c3133392c33365d2c22696e6465786573223a5b302c312c332c342c362c382c392c31302c31312c31322c31342c31382c32312c32322c32332c32352c32362c32372c33302c33332c33342c33382c34312c34332c35302c35382c35392c36302c36312c36322c36372c36392c37312c37332c37352c37362c37372c38312c38322c38332c38342c39302c39312c39322c39332c39372c39385d2c227369676e65725f696e646578223a327d".to_string(), + won_indexes: vec![1, 3], + } + } + + fn golden_message_actual() -> RegisterSignatureMessage { RegisterSignatureMessage { signed_entity_type: SignedEntityType::MithrilStakeDistribution(Epoch(246)), party_id: "party_id".to_string(), signature: "7b227369676d61223a5b3133302c3137372c31352c3232392c32342c3235312c3234372c3137312c3139362c3231302c3134332c3131332c38362c3138392c39322c35362c3131322c33332c3139332c3231322c35342c3231342c32382c3231362c3232372c3137332c3130302c3132372c3137382c34302c39382c38372c32392c3138312c3235352c3131312c3135372c3232342c3233352c34362c3130302c3136392c3233322c3138392c3235322c38322c3133392c33365d2c22696e6465786573223a5b302c312c332c342c362c382c392c31302c31312c31322c31342c31382c32312c32322c32332c32352c32362c32372c33302c33332c33342c33382c34312c34332c35302c35382c35392c36302c36312c36322c36372c36392c37312c37332c37352c37362c37372c38312c38322c38332c38342c39302c39312c39322c39332c39372c39385d2c227369676e65725f696e646578223a327d".to_string(), won_indexes: vec![1, 3], + signed_message: Some("6a7e737c312972d2346b65ac3075696e04286d046dddaf8004121e3d5e27cc0d".to_string()), } } - // Test the retro compatibility with possible future upgrades. + const ACTUAL_JSON: &str = r#"{ + "entity_type": { "MithrilStakeDistribution": 246 }, + "party_id": "party_id", + "signature": "7b227369676d61223a5b3133302c3137372c31352c3232392c32342c3235312c3234372c3137312c3139362c3231302c3134332c3131332c38362c3138392c39322c35362c3131322c33332c3139332c3231322c35342c3231342c32382c3231362c3232372c3137332c3130302c3132372c3137382c34302c39382c38372c32392c3138312c3235352c3131312c3135372c3232342c3233352c34362c3130302c3136392c3233322c3138392c3235322c38322c3133392c33365d2c22696e6465786573223a5b302c312c332c342c362c382c392c31302c31312c31322c31342c31382c32312c32322c32332c32352c32362c32372c33302c33332c33342c33382c34312c34332c35302c35382c35392c36302c36312c36322c36372c36392c37312c37332c37352c37362c37372c38312c38322c38332c38342c39302c39312c39322c39332c39372c39385d2c227369676e65725f696e646578223a327d", + "indexes": [1, 3], + "signed_message": "6a7e737c312972d2346b65ac3075696e04286d046dddaf8004121e3d5e27cc0d" + }"#; + + #[test] + fn test_actual_json_deserialized_into_previous_message() { + let json = ACTUAL_JSON; + let message: RegisterSignatureMessagePrevious = serde_json::from_str(json).unwrap(); + + assert_eq!(golden_message_previous(), message); + } + #[test] - fn test_v1() { - let json = r#"{ -"entity_type": { "MithrilStakeDistribution": 246 }, -"party_id": "party_id", -"signature": "7b227369676d61223a5b3133302c3137372c31352c3232392c32342c3235312c3234372c3137312c3139362c3231302c3134332c3131332c38362c3138392c39322c35362c3131322c33332c3139332c3231322c35342c3231342c32382c3231362c3232372c3137332c3130302c3132372c3137382c34302c39382c38372c32392c3138312c3235352c3131312c3135372c3232342c3233352c34362c3130302c3136392c3233322c3138392c3235322c38322c3133392c33365d2c22696e6465786573223a5b302c312c332c342c362c382c392c31302c31312c31322c31342c31382c32312c32322c32332c32352c32362c32372c33302c33332c33342c33382c34312c34332c35302c35382c35392c36302c36312c36322c36372c36392c37312c37332c37352c37362c37372c38312c38322c38332c38342c39302c39312c39322c39332c39372c39385d2c227369676e65725f696e646578223a327d", -"indexes": [1, 3] -}"#; + fn test_actual_json_deserialized_into_actual_message() { + let json = ACTUAL_JSON; let message: RegisterSignatureMessage = serde_json::from_str(json).expect( "This JSON is expected to be successfully parsed into a RegisterSignatureMessage instance.", ); - assert_eq!(golden_message(), message); + assert_eq!(golden_message_actual(), message); } } diff --git a/mithril-signer/src/message_adapters/to_register_signature_message.rs b/mithril-signer/src/message_adapters/to_register_signature_message.rs index ae9bc01e4b9..c6c50f4618c 100644 --- a/mithril-signer/src/message_adapters/to_register_signature_message.rs +++ b/mithril-signer/src/message_adapters/to_register_signature_message.rs @@ -18,6 +18,7 @@ impl TryToMessageAdapter<(SignedEntityType, SingleSignatures), RegisterSignature "'ToRegisterSignatureMessageAdapter' can not convert the single signature" })?, won_indexes: single_signature.won_indexes, + signed_message: None, }; Ok(message) diff --git a/mithril-test-lab/mithril-end-to-end/src/stress_test/payload_builder.rs b/mithril-test-lab/mithril-end-to-end/src/stress_test/payload_builder.rs index 4ff6162c0cc..ce847989df8 100644 --- a/mithril-test-lab/mithril-end-to-end/src/stress_test/payload_builder.rs +++ b/mithril-test-lab/mithril-end-to-end/src/stress_test/payload_builder.rs @@ -58,6 +58,7 @@ pub fn generate_register_signature_message( party_id: s.party_id.clone(), signature: s.signature.clone().to_json_hex().unwrap(), won_indexes: s.won_indexes.clone(), + signed_message: None, }) .collect::>() } From d6991b170d0288730bbcff287735abe1d06f22c7 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:23:27 +0200 Subject: [PATCH 3/6] Add signed message to `entities::SingleSignatures` in common Else we would need to change signatures of multiple methods in the signer in order to pass it to the `RegisterSignnatureMessage`. It will also be usefull in aggregator to handle signature buffer on the service side (since most services use entities instead of messages). --- .../src/database/record/single_signature.rs | 1 + .../src/message_adapters/from_register_signature.rs | 12 ++++++++++-- mithril-common/src/entities/single_signatures.rs | 8 ++++++++ .../to_register_signature_message.rs | 9 ++++++--- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/mithril-aggregator/src/database/record/single_signature.rs b/mithril-aggregator/src/database/record/single_signature.rs index 2d093d772b0..ae35a229336 100644 --- a/mithril-aggregator/src/database/record/single_signature.rs +++ b/mithril-aggregator/src/database/record/single_signature.rs @@ -54,6 +54,7 @@ impl TryFrom for SingleSignatures { party_id: value.signer_id, won_indexes: value.lottery_indexes, signature: value.signature.try_into()?, + signed_message: None, }; Ok(signatures) diff --git a/mithril-aggregator/src/message_adapters/from_register_signature.rs b/mithril-aggregator/src/message_adapters/from_register_signature.rs index e700c8906f1..ad1dd3a759f 100644 --- a/mithril-aggregator/src/message_adapters/from_register_signature.rs +++ b/mithril-aggregator/src/message_adapters/from_register_signature.rs @@ -22,6 +22,7 @@ impl TryFromMessageAdapter "'FromRegisterSingleSignatureAdapter' can not convert the single signature" })?, won_indexes: register_single_signature_message.won_indexes, + signed_message: register_single_signature_message.signed_message, }; Ok(signatures) @@ -34,9 +35,16 @@ mod tests { #[test] fn test_simple_message() { - let message = RegisterSignatureMessage::dummy(); - let signatures = FromRegisterSingleSignatureAdapter::try_adapt(message).unwrap(); + let signatures = FromRegisterSingleSignatureAdapter::try_adapt(RegisterSignatureMessage { + signed_message: Some("signed_message".to_string()), + ..RegisterSignatureMessage::dummy() + }) + .unwrap(); assert_eq!("party_id".to_string(), signatures.party_id); + assert_eq!( + Some("signed_message".to_string()), + signatures.signed_message + ); } } diff --git a/mithril-common/src/entities/single_signatures.rs b/mithril-common/src/entities/single_signatures.rs index 991c79701db..345d437509c 100644 --- a/mithril-common/src/entities/single_signatures.rs +++ b/mithril-common/src/entities/single_signatures.rs @@ -20,6 +20,13 @@ pub struct SingleSignatures { /// The indexes of the won lotteries that lead to the single signatures #[serde(rename = "indexes")] pub won_indexes: Vec, + + /// Message that is signed by the signer + /// + /// Used to buffer the signature for later if the Aggregator has yet to create an open message + /// for the signed entity type. + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_message: Option, } impl SingleSignatures { @@ -33,6 +40,7 @@ impl SingleSignatures { party_id, signature, won_indexes, + signed_message: None, } } diff --git a/mithril-signer/src/message_adapters/to_register_signature_message.rs b/mithril-signer/src/message_adapters/to_register_signature_message.rs index c6c50f4618c..666c935cd5c 100644 --- a/mithril-signer/src/message_adapters/to_register_signature_message.rs +++ b/mithril-signer/src/message_adapters/to_register_signature_message.rs @@ -18,7 +18,7 @@ impl TryToMessageAdapter<(SignedEntityType, SingleSignatures), RegisterSignature "'ToRegisterSignatureMessageAdapter' can not convert the single signature" })?, won_indexes: single_signature.won_indexes, - signed_message: None, + signed_message: single_signature.signed_message, }; Ok(message) @@ -33,13 +33,16 @@ mod tests { #[test] fn adapt_ok() { - let single_signature = fake_data::single_signatures([1, 3].to_vec()); let message: RegisterSignatureMessage = ToRegisterSignatureMessageAdapter::try_adapt(( SignedEntityType::dummy(), - single_signature, + SingleSignatures { + signed_message: Some("signed_message".to_string()), + ..fake_data::single_signatures([1, 3].to_vec()) + }, )) .unwrap(); assert_eq!("party_id".to_string(), message.party_id); + assert_eq!(Some("signed_message".to_string()), message.signed_message); } } From f2611bbac0ce7a0e18e4964bd0d81104804e9f08 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:59:37 +0200 Subject: [PATCH 4/6] Include signed message when computing Single signatures --- .../src/entities/single_signatures.rs | 17 +++++++++- mithril-common/src/protocol/single_signer.rs | 34 +++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/mithril-common/src/entities/single_signatures.rs b/mithril-common/src/entities/single_signatures.rs index 345d437509c..3c12acc2ba8 100644 --- a/mithril-common/src/entities/single_signatures.rs +++ b/mithril-common/src/entities/single_signatures.rs @@ -30,7 +30,7 @@ pub struct SingleSignatures { } impl SingleSignatures { - /// SingleSignature factory + /// `SingleSignatures` factory pub fn new( party_id: PartyId, signature: ProtocolSingleSignature, @@ -44,6 +44,21 @@ impl SingleSignatures { } } + /// `SingleSignatures` factory including the signed message + pub fn new_with_signed_message( + party_id: PartyId, + signature: ProtocolSingleSignature, + won_indexes: Vec, + signed_message: String, + ) -> SingleSignatures { + SingleSignatures { + party_id, + signature, + won_indexes, + signed_message: Some(signed_message), + } + } + /// Convert this [SingleSignatures] to its corresponding [MithrilStm Signature][StmSig]. pub fn to_protocol_signature(&self) -> StmSig { self.signature.clone().into() diff --git a/mithril-common/src/protocol/single_signer.rs b/mithril-common/src/protocol/single_signer.rs index e04ce11bf48..97a430e2642 100644 --- a/mithril-common/src/protocol/single_signer.rs +++ b/mithril-common/src/protocol/single_signer.rs @@ -23,14 +23,16 @@ impl SingleSigner { /// /// If no lottery are won None will be returned. pub fn sign(&self, message: &ProtocolMessage) -> StdResult> { - match self.protocol_signer.sign(message.compute_hash().as_bytes()) { + let signed_message = message.compute_hash(); + match self.protocol_signer.sign(signed_message.as_bytes()) { Some(signature) => { let won_indexes = signature.indexes.clone(); - Ok(Some(SingleSignatures::new( + Ok(Some(SingleSignatures::new_with_signed_message( self.party_id.to_owned(), signature.into(), won_indexes, + signed_message, ))) } None => Ok(None), @@ -72,4 +74,32 @@ mod test { assert!(signature.is_some()); } + + #[test] + fn embed_signed_message_in_issued_signature() { + let fixture = MithrilFixtureBuilder::default().with_signers(3).build(); + let signers = fixture.signers_fixture(); + let signer = signers.first().unwrap(); + + let (single_signer, _) = SignerBuilder::new( + &fixture.signers_with_stake(), + &fixture.protocol_parameters(), + ) + .unwrap() + .build_test_single_signer( + signer.signer_with_stake.clone(), + signer.kes_secret_key_path(), + ) + .unwrap(); + + let message = ProtocolMessage::default(); + let signature = single_signer + .sign(&message) + .expect("Single signer should be able to issue single signature"); + + assert_eq!( + Some(message.compute_hash()), + signature.and_then(|s| s.signed_message) + ); + } } From 9c29469b98dfc56ecae09f65d0247a04b236c265 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:03:14 +0200 Subject: [PATCH 5/6] Fix PR reviews remarks: enhance code doc --- mithril-common/src/entities/single_signatures.rs | 2 +- mithril-common/src/messages/register_signature.rs | 2 +- openapi.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mithril-common/src/entities/single_signatures.rs b/mithril-common/src/entities/single_signatures.rs index 3c12acc2ba8..1cd5f66f423 100644 --- a/mithril-common/src/entities/single_signatures.rs +++ b/mithril-common/src/entities/single_signatures.rs @@ -23,7 +23,7 @@ pub struct SingleSignatures { /// Message that is signed by the signer /// - /// Used to buffer the signature for later if the Aggregator has yet to create an open message + /// Used to buffer the signature for later if the aggregator has yet to create an open message /// for the signed entity type. #[serde(skip_serializing_if = "Option::is_none")] pub signed_message: Option, diff --git a/mithril-common/src/messages/register_signature.rs b/mithril-common/src/messages/register_signature.rs index e74f744192e..b2dc8a6d571 100644 --- a/mithril-common/src/messages/register_signature.rs +++ b/mithril-common/src/messages/register_signature.rs @@ -24,7 +24,7 @@ pub struct RegisterSignatureMessage { /// Message that is signed by the signer /// - /// Used to buffer the signature for later if the Aggregator has yet to create an open message + /// Used to buffer the signature for later if the aggregator has yet to create an open message /// for the signed entity type. #[serde(skip_serializing_if = "Option::is_none")] pub signed_message: Option, diff --git a/openapi.yaml b/openapi.yaml index 54dbb9e35d8..c12490b1dba 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -1072,8 +1072,8 @@ components: description: | Hash of the protocol message that is signed by the signer - Optional, allow the aggregator to store this signature for later if it has yet to start to work - on the message. + Optional, allows the aggregator to store this signature for later if it has yet to start aggregating + signatures for the message. type: string format: bytes example: From 064aa0a37f7437513432aa460d5e95ae42155e4b Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:10:37 +0200 Subject: [PATCH 6/6] Upgrade crates versions * Mithril-aggregator from `0.5.57` to `0.5.58` * Mithril-signer from `0.2.175` to `0.2.176` * Mithril-common from `0.4.47` to `0.4.48` * Mithril-end-to-end from `0.4.29` to `0.4.30` --- Cargo.lock | 8 ++++---- mithril-aggregator/Cargo.toml | 2 +- mithril-common/Cargo.toml | 2 +- mithril-signer/Cargo.toml | 2 +- mithril-test-lab/mithril-end-to-end/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea77e0c8c85..ce69852fa8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3552,7 +3552,7 @@ dependencies = [ [[package]] name = "mithril-aggregator" -version = "0.5.57" +version = "0.5.58" dependencies = [ "anyhow", "async-trait", @@ -3708,7 +3708,7 @@ dependencies = [ [[package]] name = "mithril-common" -version = "0.4.47" +version = "0.4.48" dependencies = [ "anyhow", "async-trait", @@ -3780,7 +3780,7 @@ dependencies = [ [[package]] name = "mithril-end-to-end" -version = "0.4.29" +version = "0.4.30" dependencies = [ "anyhow", "async-recursion", @@ -3853,7 +3853,7 @@ dependencies = [ [[package]] name = "mithril-signer" -version = "0.2.175" +version = "0.2.176" dependencies = [ "anyhow", "async-trait", diff --git a/mithril-aggregator/Cargo.toml b/mithril-aggregator/Cargo.toml index e6abc25d01b..54275e14ee6 100644 --- a/mithril-aggregator/Cargo.toml +++ b/mithril-aggregator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-aggregator" -version = "0.5.57" +version = "0.5.58" description = "A Mithril Aggregator server" authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-common/Cargo.toml b/mithril-common/Cargo.toml index 232bcb3ad56..692383c2810 100644 --- a/mithril-common/Cargo.toml +++ b/mithril-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-common" -version = "0.4.47" +version = "0.4.48" description = "Common types, interfaces, and utilities for Mithril nodes." authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-signer/Cargo.toml b/mithril-signer/Cargo.toml index fbc4723ff89..b15e7782a81 100644 --- a/mithril-signer/Cargo.toml +++ b/mithril-signer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-signer" -version = "0.2.175" +version = "0.2.176" description = "A Mithril Signer" authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-test-lab/mithril-end-to-end/Cargo.toml b/mithril-test-lab/mithril-end-to-end/Cargo.toml index 29d76af58df..6aa995c1946 100644 --- a/mithril-test-lab/mithril-end-to-end/Cargo.toml +++ b/mithril-test-lab/mithril-end-to-end/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-end-to-end" -version = "0.4.29" +version = "0.4.30" authors = { workspace = true } edition = { workspace = true } documentation = { workspace = true }