diff --git a/Cargo.lock b/Cargo.lock index 90594e30ae8..c734ff531a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4493,7 +4493,7 @@ dependencies = [ [[package]] name = "mithril-signer" -version = "0.2.271" +version = "0.2.272" dependencies = [ "anyhow", "async-trait", diff --git a/mithril-signer/Cargo.toml b/mithril-signer/Cargo.toml index 8767d48ee7f..d1b07a3b626 100644 --- a/mithril-signer/Cargo.toml +++ b/mithril-signer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-signer" -version = "0.2.271" +version = "0.2.272" description = "A Mithril Signer" authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-signer/src/database/query/protocol_initializer/insert_protocol_initializer.rs b/mithril-signer/src/database/query/protocol_initializer/insert_protocol_initializer.rs index 58bb70189e4..f3b222ef213 100644 --- a/mithril-signer/src/database/query/protocol_initializer/insert_protocol_initializer.rs +++ b/mithril-signer/src/database/query/protocol_initializer/insert_protocol_initializer.rs @@ -5,12 +5,12 @@ use mithril_persistence::sqlite::{Query, SourceAlias, SqLiteEntity, WhereConditi use crate::database::record::ProtocolInitializerRecord; -/// Query to insert or replace [ProtocolInitializerRecord] in the sqlite database -pub struct InsertOrReplaceProtocolInitializerQuery { +/// Query to insert or ignore [ProtocolInitializerRecord] in the sqlite database +pub struct InsertOrIgnoreProtocolInitializerQuery { condition: WhereCondition, } -impl InsertOrReplaceProtocolInitializerQuery { +impl InsertOrIgnoreProtocolInitializerQuery { pub fn one(record: ProtocolInitializerRecord) -> StdResult { let value = serde_json::to_string(&record.protocol_initializer).unwrap(); let condition = WhereCondition::new( @@ -26,7 +26,7 @@ impl InsertOrReplaceProtocolInitializerQuery { } } -impl Query for InsertOrReplaceProtocolInitializerQuery { +impl Query for InsertOrIgnoreProtocolInitializerQuery { type Entity = ProtocolInitializerRecord; fn filters(&self) -> WhereCondition { @@ -41,6 +41,6 @@ impl Query for InsertOrReplaceProtocolInitializerQuery { "protocol_initializer", )])); - format!("insert or replace into protocol_initializer {condition} returning {projection}") + format!("insert or ignore into protocol_initializer {condition} returning {projection} ") } } diff --git a/mithril-signer/src/database/repository/protocol_initializer_repository.rs b/mithril-signer/src/database/repository/protocol_initializer_repository.rs index dbeab626aee..46ca2041ef1 100644 --- a/mithril-signer/src/database/repository/protocol_initializer_repository.rs +++ b/mithril-signer/src/database/repository/protocol_initializer_repository.rs @@ -4,7 +4,7 @@ use anyhow::Ok; use async_trait::async_trait; use crate::database::query::{ - DeleteProtocolInitializerQuery, InsertOrReplaceProtocolInitializerQuery, + DeleteProtocolInitializerQuery, InsertOrIgnoreProtocolInitializerQuery, }; use crate::database::record::ProtocolInitializerRecord; use crate::{ @@ -62,7 +62,7 @@ impl ProtocolInitializerStorer for ProtocolInitializerRepository { created_at: chrono::Utc::now(), }; self.connection - .apply(InsertOrReplaceProtocolInitializerQuery::one(record).unwrap())?; + .apply(InsertOrIgnoreProtocolInitializerQuery::one(record).unwrap())?; Ok(previous_protocol_initializer) } diff --git a/mithril-signer/src/database/tests/protocol_initializer.rs b/mithril-signer/src/database/tests/protocol_initializer.rs index f41179fe914..4609e6a79bc 100644 --- a/mithril-signer/src/database/tests/protocol_initializer.rs +++ b/mithril-signer/src/database/tests/protocol_initializer.rs @@ -13,7 +13,7 @@ fn setup_protocol_initializers(nb_epoch: u64) -> Vec<(Epoch, ProtocolInitializer let mut values: Vec<(Epoch, ProtocolInitializer)> = Vec::new(); for epoch in 1..=nb_epoch { let stake = (epoch + 1) * 100; - let protocol_initializer = fake_data::protocol_initializer("1", stake); + let protocol_initializer = fake_data::protocol_initializer(format!("{epoch:?}"), stake); values.push((Epoch(epoch), protocol_initializer)); } values @@ -84,6 +84,37 @@ mod request { ); } + #[tokio::test] + async fn protocol_initializer_in_store_is_created_once_per_epoch_and_never_updated() { + let protocol_initializers = setup_protocol_initializers(2); + let epoch = protocol_initializers[0].0; + let first_protocol_initializer = protocol_initializers[0].1.clone(); + let second_protocol_initializer = protocol_initializers[1].1.clone(); + + let store = init_store(&[], None).await; + store + .save_protocol_initializer(epoch, first_protocol_initializer.clone()) + .await + .unwrap(); + + let res = store.get_protocol_initializer(epoch).await.unwrap().unwrap(); + assert_eq!( + serde_json::to_string(&first_protocol_initializer).unwrap(), + serde_json::to_string(&res).unwrap() + ); + + store + .save_protocol_initializer(epoch, second_protocol_initializer.clone()) + .await + .unwrap(); + + let res = store.get_protocol_initializer(epoch).await.unwrap().unwrap(); + assert_eq!( + serde_json::to_string(&first_protocol_initializer).unwrap(), + serde_json::to_string(&res).unwrap() + ); + } + #[tokio::test] async fn get_protocol_initializer_for_empty_epoch() { let store = init_store(&setup_protocol_initializers(2), None).await; diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 2beebabe441..e558d26a87e 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -211,6 +211,20 @@ impl Runner for SignerRunner { self.services.kes_signer.clone(), kes_period, )?; + self.services + .protocol_initializer_store + .save_protocol_initializer(epoch_offset_to_recording_epoch, protocol_initializer) + .await?; + + let protocol_initializer = self + .services + .protocol_initializer_store + .get_protocol_initializer(epoch_offset_to_recording_epoch) + .await?.ok_or(RunnerError::NoValueError( + format!("no protocol_initializer available in store for epoch {epoch_offset_to_recording_epoch}"), + )).with_context( + || "register_signer_to_aggregator can not retrieve protocol initializer from store", + )?; let signer = Signer::new( self.services.single_signer.get_party_id(), protocol_initializer.verification_key().into(), @@ -222,10 +236,6 @@ impl Runner for SignerRunner { .certificate_handler .register_signer(epoch_offset_to_recording_epoch, &signer) .await?; - self.services - .protocol_initializer_store - .save_protocol_initializer(epoch_offset_to_recording_epoch, protocol_initializer) - .await?; Ok(()) } @@ -682,15 +692,37 @@ mod tests { .await .expect("registering a signer to the aggregator should not fail"); - assert!(certificate_handler.get_last_registered_signer().await.is_some()); - let maybe_protocol_initializer = protocol_initializer_store + let last_registered_signer_first_registration = + certificate_handler.get_last_registered_signer().await.unwrap(); + let maybe_protocol_initializer_first_registration = protocol_initializer_store .get_protocol_initializer(current_epoch.offset_to_recording_epoch()) .await .expect("get_protocol_initializer should not fail"); assert!( - maybe_protocol_initializer.is_some(), + maybe_protocol_initializer_first_registration.is_some(), "A protocol initializer should have been registered at the 'Recording' epoch" ); + + runner + .register_signer_to_aggregator() + .await + .expect("registering a signer to the aggregator should not fail"); + + let last_registered_signer_second_registration = + certificate_handler.get_last_registered_signer().await.unwrap(); + let maybe_protocol_initializer_second_registration = protocol_initializer_store + .get_protocol_initializer(current_epoch.offset_to_recording_epoch()) + .await + .expect("get_protocol_initializer should not fail"); + assert!( + maybe_protocol_initializer_second_registration.is_some(), + "A protocol initializer should have been registered at the 'Recording' epoch" + ); + assert_eq!( + serde_json::to_string(&last_registered_signer_first_registration).unwrap(), + serde_json::to_string(&last_registered_signer_second_registration).unwrap(), + "The signer registration should be the same and should have been registered twice" + ); } #[tokio::test]