From 1320060188ccfbcf42df598fd3aaebadb240e202 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Thu, 3 Oct 2024 16:20:07 +0200 Subject: [PATCH 01/13] feat: add `protocol_initializer` to signer epoch service --- mithril-common/src/test_utils/fake_data.rs | 27 ++++ .../src/dependency_injection/builder.rs | 5 +- mithril-signer/src/runtime/runner.rs | 26 ++-- mithril-signer/src/services/epoch_service.rs | 131 +++++++++++++++--- .../src/store/protocol_initializer_store.rs | 22 +-- .../test_extensions/state_machine_tester.rs | 5 +- 6 files changed, 163 insertions(+), 53 deletions(-) diff --git a/mithril-common/src/test_utils/fake_data.rs b/mithril-common/src/test_utils/fake_data.rs index 6d9e6f7e572..4f7ae052e29 100644 --- a/mithril-common/src/test_utils/fake_data.rs +++ b/mithril-common/src/test_utils/fake_data.rs @@ -52,6 +52,33 @@ pub fn protocol_parameters() -> entities::ProtocolParameters { entities::ProtocolParameters::new(k, m, phi_f) } +cfg_random! { + /// Fake ProtocolInitializer + pub fn protocol_initializer>( + seed: S, + stake: entities::Stake, + ) -> crypto_helper::ProtocolInitializer { + use rand_chacha::ChaCha20Rng; + use rand_core::SeedableRng; + + let protocol_parameters = protocol_parameters(); + let seed: [u8; 32] = format!("{:<032}", seed.into()).as_bytes()[..32] + .try_into() + .unwrap(); + let mut rng = ChaCha20Rng::from_seed(seed); + let kes_secret_key_path: Option = None; + let kes_period = Some(0); + + crypto_helper::ProtocolInitializer::setup( + protocol_parameters.into(), + kes_secret_key_path, + kes_period, + stake, + &mut rng, + ).unwrap() + } +} + /// Fake CertificatePending pub fn certificate_pending() -> entities::CertificatePending { // Epoch diff --git a/mithril-signer/src/dependency_injection/builder.rs b/mithril-signer/src/dependency_injection/builder.rs index 6ee7b5fbfed..ba756066331 100644 --- a/mithril-signer/src/dependency_injection/builder.rs +++ b/mithril-signer/src/dependency_injection/builder.rs @@ -322,7 +322,10 @@ impl<'a> DependenciesBuilder<'a> { let cardano_stake_distribution_signable_builder = Arc::new( CardanoStakeDistributionSignableBuilder::new(stake_store.clone()), ); - let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new(stake_store.clone()))); + let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new( + stake_store.clone(), + protocol_initializer_store.clone(), + ))); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), single_signer.clone(), diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 1dbd5ecd27f..938f37f3797 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -287,6 +287,7 @@ impl Runner for SignerRunner { epoch_settings, aggregator_features.capabilities.signed_entity_types, ) + .await } async fn compute_message( @@ -413,10 +414,8 @@ impl Runner for SignerRunner { mod tests { use mockall::mock; use mockall::predicate::eq; - use rand_chacha::ChaCha20Rng; - use rand_core::SeedableRng; use std::collections::BTreeSet; - use std::{path::Path, path::PathBuf, sync::Arc}; + use std::{path::Path, sync::Arc}; use tokio::sync::RwLock; use mithril_common::{ @@ -496,7 +495,7 @@ mod tests { #[async_trait] impl EpochService for FakeEpochServiceImpl { - fn inform_epoch_settings( + async fn inform_epoch_settings( &mut self, _epoch_settings: SignerEpochSettings, _allowed_discriminants: BTreeSet, @@ -509,6 +508,9 @@ mod tests { fn next_protocol_parameters(&self) -> StdResult<&ProtocolParameters> { unimplemented!() } + fn protocol_initializer(&self) -> StdResult<&Option> { + Ok(&None) + } fn current_signers(&self) -> StdResult<&Vec> { unimplemented!() } @@ -550,14 +552,7 @@ mod tests { } fn dummy_protocol_initializer() -> ProtocolInitializer { - ProtocolInitializer::setup( - fake_data::protocol_parameters().into(), - None::, - Some(0), - 1234, - &mut ChaCha20Rng::from_seed([0; 32]), - ) - .unwrap() + fake_data::protocol_initializer("party", 1234) } async fn init_services() -> SignerDependencyContainer { @@ -611,10 +606,13 @@ mod tests { let cardano_stake_distribution_builder = Arc::new( CardanoStakeDistributionSignableBuilder::new(stake_store.clone()), ); - let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new(stake_store.clone()))); - let single_signer = Arc::new(MithrilSingleSigner::new(party_id)); let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new(Box::new(adapter), None)); + let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new( + stake_store.clone(), + protocol_initializer_store.clone(), + ))); + let single_signer = Arc::new(MithrilSingleSigner::new(party_id)); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), single_signer.clone(), diff --git a/mithril-signer/src/services/epoch_service.rs b/mithril-signer/src/services/epoch_service.rs index bbae068b12f..cfc6720e061 100644 --- a/mithril-signer/src/services/epoch_service.rs +++ b/mithril-signer/src/services/epoch_service.rs @@ -16,6 +16,7 @@ use mithril_persistence::store::StakeStorer; use crate::dependency_injection::EpochServiceWrapper; use crate::entities::SignerEpochSettings; use crate::services::SignedEntityConfigProvider; +use crate::store::ProtocolInitializerStorer; use crate::RunnerError; /// Errors dedicated to the EpochService. @@ -31,7 +32,7 @@ pub enum EpochServiceError { pub trait EpochService: Sync + Send { /// Inform the service a new epoch has been detected, telling it to update its /// internal state for the new epoch. - fn inform_epoch_settings( + async fn inform_epoch_settings( &mut self, epoch_settings: SignerEpochSettings, allowed_discriminants: BTreeSet, @@ -43,6 +44,11 @@ pub trait EpochService: Sync + Send { /// Get next protocol parameters used in next epoch (associated with the actual epoch) fn next_protocol_parameters(&self) -> StdResult<&ProtocolParameters>; + /// Get the protocol initializer for the current epoch if any + /// + /// `None` if the signer can't sign for the current epoch. + fn protocol_initializer(&self) -> StdResult<&Option>; + /// Get signers for the current epoch fn current_signers(&self) -> StdResult<&Vec>; @@ -79,6 +85,7 @@ pub trait EpochService: Sync + Send { struct EpochData { epoch: Epoch, next_protocol_parameters: ProtocolParameters, + protocol_initializer: Option, current_signers: Vec, next_signers: Vec, allowed_discriminants: BTreeSet, @@ -89,14 +96,19 @@ struct EpochData { /// Implementation of the [epoch service][EpochService]. pub struct MithrilEpochService { stake_storer: Arc, + protocol_initializer_store: Arc, epoch_data: Option, } impl MithrilEpochService { /// Create a new service instance - pub fn new(stake_storer: Arc) -> Self { + pub fn new( + stake_storer: Arc, + protocol_initializer_store: Arc, + ) -> Self { Self { stake_storer, + protocol_initializer_store, epoch_data: None, } } @@ -148,7 +160,7 @@ impl MithrilEpochService { #[async_trait] impl EpochService for MithrilEpochService { - fn inform_epoch_settings( + async fn inform_epoch_settings( &mut self, epoch_settings: SignerEpochSettings, allowed_discriminants: BTreeSet, @@ -158,9 +170,16 @@ impl EpochService for MithrilEpochService { epoch_settings ); + let epoch = epoch_settings.epoch; + let protocol_initializer = self + .protocol_initializer_store + .get_protocol_initializer(epoch.offset_to_signer_retrieval_epoch()?) + .await?; + self.epoch_data = Some(EpochData { - epoch: epoch_settings.epoch, + epoch, next_protocol_parameters: epoch_settings.next_protocol_parameters, + protocol_initializer, current_signers: epoch_settings.current_signers, next_signers: epoch_settings.next_signers, allowed_discriminants, @@ -180,6 +199,10 @@ impl EpochService for MithrilEpochService { Ok(&self.unwrap_data()?.next_protocol_parameters) } + fn protocol_initializer(&self) -> StdResult<&Option> { + Ok(&self.unwrap_data()?.protocol_initializer) + } + fn current_signers(&self) -> StdResult<&Vec> { Ok(&self.unwrap_data()?.current_signers) } @@ -284,7 +307,7 @@ pub mod mock_epoch_service { impl EpochService for EpochServiceImpl { /// Inform the service a new epoch has been detected, telling it to update its /// internal state for the new epoch. - fn inform_epoch_settings( + async fn inform_epoch_settings( &mut self, epoch_settings: SignerEpochSettings, allowed_discriminants: BTreeSet, @@ -296,6 +319,8 @@ pub mod mock_epoch_service { /// Get next protocol parameters used in next epoch (associated with the actual epoch) fn next_protocol_parameters(&self) -> StdResult<&'static ProtocolParameters>; + fn protocol_initializer(&self) -> StdResult<&'static Option>; + /// Get signers for the current epoch fn current_signers(&self) -> StdResult<&'static Vec>; @@ -354,6 +379,7 @@ mod tests { use crate::entities::SignerEpochSettings; use crate::services::MithrilProtocolInitializerBuilder; + use crate::store::ProtocolInitializerStore; use super::*; @@ -369,15 +395,19 @@ mod tests { ) .unwrap(); let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); - let service = MithrilEpochService::new(stake_store); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + let service = MithrilEpochService::new(stake_store, protocol_initializer_store); service .is_signer_included_in_current_stake_distribution(party_id, protocol_initializer) .expect_err("can_signer_sign should return error when epoch settings is not set"); } - #[test] - fn test_is_signer_included_in_current_stake_distribution_returns_true_when_signer_verification_key_and_pool_id_found( + #[tokio::test] + async fn test_is_signer_included_in_current_stake_distribution_returns_true_when_signer_verification_key_and_pool_id_found( ) { let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); let protocol_initializer = fixtures.signers_fixture()[0] @@ -386,15 +416,21 @@ mod tests { let epoch = Epoch(12); let signers = fixtures.signers(); let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + let epoch_settings = SignerEpochSettings { epoch, current_signers: signers[..5].to_vec(), ..SignerEpochSettings::dummy().clone() }; - let mut service = MithrilEpochService::new(stake_store); + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); service .inform_epoch_settings(epoch_settings.clone(), BTreeSet::new()) + .await .unwrap(); let party_id = fixtures.signers_fixture()[0].party_id(); @@ -435,17 +471,22 @@ mod tests { .map(|(i, signer)| (signer.party_id.clone(), (i + 1) as u64 * 100)) .collect(); - // Init stake_store + // Init stores let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); stake_store .save_stakes(epoch, stake_distribution.clone()) .await .expect("save_stakes should not fail"); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); // Build service and register epoch settings - let service = MithrilEpochService::new(stake_store); + let service = MithrilEpochService::new(stake_store, protocol_initializer_store); assert!(service.epoch_of_current_data().is_err()); assert!(service.next_protocol_parameters().is_err()); + assert!(service.protocol_initializer().is_err()); assert!(service.current_signers().is_err()); assert!(service.next_signers().is_err()); assert!(service.current_signers_with_stake().await.is_err()); @@ -454,14 +495,18 @@ mod tests { assert!(service.next_cardano_transactions_signing_config().is_err()); } - #[test] - fn test_data_are_available_after_register_epoch_settings_call() { + #[tokio::test] + async fn test_data_are_available_after_register_epoch_settings_call() { let epoch = Epoch(12); // Signers and stake distribution let signers = fake_data::signers(10); - // Init stake_store + // Init stores let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); // Epoch settings let epoch_settings = SignerEpochSettings { @@ -472,13 +517,14 @@ mod tests { }; // Build service and register epoch settings - let mut service = MithrilEpochService::new(stake_store); + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); service .inform_epoch_settings( epoch_settings.clone(), BTreeSet::from([SignedEntityTypeDiscriminants::CardanoImmutableFilesFull]), ) + .await .unwrap(); // Check current_signers @@ -503,6 +549,10 @@ mod tests { epoch_settings.next_protocol_parameters, *service.next_protocol_parameters().unwrap() ); + assert!( + service.protocol_initializer().unwrap().is_none(), + "protocol_initializer should be None since nothing was in store" + ); // Check allowed_discriminants assert_eq!( @@ -555,6 +605,10 @@ mod tests { ), None, )); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); // Epoch settings let epoch_settings = SignerEpochSettings { @@ -565,9 +619,10 @@ mod tests { }; // Build service and register epoch settings - let mut service = MithrilEpochService::new(stake_store); + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); service .inform_epoch_settings(epoch_settings.clone(), BTreeSet::new()) + .await .unwrap(); // Check current signers with stake @@ -593,13 +648,53 @@ mod tests { } } + #[tokio::test] + async fn test_protocol_initializer_is_available_after_register_epoch_settings_call_if_in_store() + { + let epoch = Epoch(12); + let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new( + MemoryAdapter::new(Some(vec![( + epoch.offset_to_signer_retrieval_epoch().unwrap(), + fake_data::protocol_initializer("seed", 1245), + )])) + .unwrap(), + ), + None, + )); + + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); + let epoch_settings = SignerEpochSettings { + epoch, + ..SignerEpochSettings::dummy().clone() + }; + service + .inform_epoch_settings(epoch_settings, BTreeSet::new()) + .await + .unwrap(); + + let protocol_initializer = service.protocol_initializer().unwrap(); + assert_eq!( + Some(1245), + protocol_initializer.as_ref().map(|p| p.get_stake()), + ); + } + #[tokio::test] async fn is_source_of_signed_entity_config() { let stake_store = Arc::new(StakeStore::new( Box::new(MemoryAdapter::::new(None).unwrap()), None, )); - let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new(stake_store))); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new( + stake_store, + protocol_initializer_store, + ))); let config_provider = SignerSignedEntityConfigProvider { cardano_network: fake_data::network(), epoch_service: epoch_service.clone(), @@ -626,6 +721,7 @@ mod tests { }, allowed_discriminants.clone(), ) + .await .unwrap(); config_provider @@ -649,6 +745,7 @@ mod tests { }, allowed_discriminants.clone(), ) + .await .unwrap(); let config = config_provider.get().await.unwrap(); diff --git a/mithril-signer/src/store/protocol_initializer_store.rs b/mithril-signer/src/store/protocol_initializer_store.rs index b37f57db754..8f8dae2a4d4 100644 --- a/mithril-signer/src/store/protocol_initializer_store.rs +++ b/mithril-signer/src/store/protocol_initializer_store.rs @@ -100,34 +100,16 @@ impl ProtocolInitializerStorer for ProtocolInitializerStore { #[cfg(test)] mod tests { - use std::path::PathBuf; - - use super::*; - use mithril_common::test_utils::fake_data; use mithril_persistence::store::adapter::MemoryAdapter; - use rand_chacha::ChaCha20Rng; - use rand_core::SeedableRng; + use super::*; 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 protocol_parameters = fake_data::protocol_parameters(); - let party_id = format!("{:<032}", 1); let stake = (epoch + 1) * 100; - let seed: [u8; 32] = party_id.as_bytes()[..32].try_into().unwrap(); - let mut rng = ChaCha20Rng::from_seed(seed); - let kes_secret_key_path: Option = None; - let kes_period = Some(0); - let protocol_initializer = ProtocolInitializer::setup( - protocol_parameters.into(), - kes_secret_key_path, - kes_period, - stake, - &mut rng, - ) - .expect("protocol initializer should not fail"); + let protocol_initializer = fake_data::protocol_initializer("1", stake); values.push((Epoch(epoch), protocol_initializer)); } values diff --git a/mithril-signer/tests/test_extensions/state_machine_tester.rs b/mithril-signer/tests/test_extensions/state_machine_tester.rs index dd9ed8d8300..dd9ca6926de 100644 --- a/mithril-signer/tests/test_extensions/state_machine_tester.rs +++ b/mithril-signer/tests/test_extensions/state_machine_tester.rs @@ -216,7 +216,10 @@ impl StateMachineTester { let cardano_stake_distribution_builder = Arc::new( CardanoStakeDistributionSignableBuilder::new(stake_store.clone()), ); - let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new(stake_store.clone()))); + let epoch_service = Arc::new(RwLock::new(MithrilEpochService::new( + stake_store.clone(), + protocol_initializer_store.clone(), + ))); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), single_signer.clone(), From 1233fece7f8837e293a16c5beac44b8ffbbfacf6 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:27:14 +0200 Subject: [PATCH 02/13] refactor: move `can_signer_sign_current_epoch` check to signer epoch service Before it was in the runner. --- mithril-signer/src/runtime/runner.rs | 179 +----------------- mithril-signer/src/services/epoch_service.rs | 184 ++++++++++++++++--- 2 files changed, 161 insertions(+), 202 deletions(-) diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 938f37f3797..9267b181ee9 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -248,27 +248,7 @@ impl Runner for SignerRunner { async fn can_sign_current_epoch(&self) -> StdResult { let epoch_service = self.epoch_service_read().await; - let epoch = epoch_service.epoch_of_current_data()?; - if let Some(protocol_initializer) = self - .services - .protocol_initializer_store - .get_protocol_initializer(epoch.offset_to_signer_retrieval_epoch()?) - .await? - { - debug!(" > got protocol initializer for this epoch ({epoch})"); - if epoch_service.is_signer_included_in_current_stake_distribution( - self.services.single_signer.get_party_id(), - protocol_initializer, - )? { - return Ok(true); - } else { - debug!(" > Signer not in current stake distribution. Can NOT sign"); - } - } else { - warn!(" > NO protocol initializer found for this epoch ({epoch})",); - } - - Ok(false) + epoch_service.can_signer_sign_current_epoch(self.services.single_signer.get_party_id()) } async fn inform_epoch_settings(&self, epoch_settings: SignerEpochSettings) -> StdResult<()> { @@ -430,8 +410,8 @@ mod tests { }, digesters::{DumbImmutableDigester, DumbImmutableFileObserver}, entities::{ - BlockNumber, BlockRange, CardanoDbBeacon, CardanoTransactionsSigningConfig, Epoch, - ProtocolMessagePartKey, ProtocolParameters, SignedEntityTypeDiscriminants, + BlockNumber, BlockRange, CardanoDbBeacon, Epoch, ProtocolMessagePartKey, + SignedEntityTypeDiscriminants, }, era::{adapters::EraReaderBootstrapAdapter, EraChecker, EraReader}, messages::{AggregatorCapabilities, AggregatorFeaturesMessage}, @@ -488,73 +468,6 @@ mod tests { } } - struct FakeEpochServiceImpl { - epoch_returned: Epoch, - can_signer_sign_current_epoch_returned: Result, - } - - #[async_trait] - impl EpochService for FakeEpochServiceImpl { - async fn inform_epoch_settings( - &mut self, - _epoch_settings: SignerEpochSettings, - _allowed_discriminants: BTreeSet, - ) -> StdResult<()> { - Ok(()) - } - fn epoch_of_current_data(&self) -> StdResult { - Ok(self.epoch_returned) - } - fn next_protocol_parameters(&self) -> StdResult<&ProtocolParameters> { - unimplemented!() - } - fn protocol_initializer(&self) -> StdResult<&Option> { - Ok(&None) - } - fn current_signers(&self) -> StdResult<&Vec> { - unimplemented!() - } - fn next_signers(&self) -> StdResult<&Vec> { - unimplemented!() - } - async fn current_signers_with_stake(&self) -> StdResult> { - Ok(vec![]) - } - async fn next_signers_with_stake(&self) -> StdResult> { - Ok(vec![]) - } - - fn allowed_discriminants(&self) -> StdResult<&BTreeSet> { - unimplemented!() - } - - fn cardano_transactions_signing_config( - &self, - ) -> StdResult<&Option> { - Ok(&None) - } - fn next_cardano_transactions_signing_config( - &self, - ) -> StdResult<&Option> { - Ok(&None) - } - - fn is_signer_included_in_current_stake_distribution( - &self, - _party_id: PartyId, - _protocol_initializer: ProtocolInitializer, - ) -> StdResult { - match &self.can_signer_sign_current_epoch_returned { - Ok(result) => Ok(*result), - Err(e) => Err(anyhow::anyhow!(e.clone())), - } - } - } - - fn dummy_protocol_initializer() -> ProtocolInitializer { - fake_data::protocol_initializer("party", 1234) - } - async fn init_services() -> SignerDependencyContainer { let sqlite_connection = Arc::new(main_db_connection().unwrap()); let adapter: MemoryAdapter = MemoryAdapter::new(None).unwrap(); @@ -781,92 +694,6 @@ mod tests { ); } - #[tokio::test] - async fn can_sign_current_epoch_returns_false_when_epoch_service_returns_false() { - let mut services = init_services().await; - let epoch_service = FakeEpochServiceImpl { - epoch_returned: Epoch(8), - can_signer_sign_current_epoch_returned: Ok(false), - }; - services.epoch_service = Arc::new(RwLock::new(epoch_service)); - - services - .protocol_initializer_store - .save_protocol_initializer(Epoch(7), dummy_protocol_initializer()) - .await - .unwrap(); - - let runner = init_runner(Some(services), None).await; - - assert!(!runner.can_sign_current_epoch().await.unwrap()); - } - - #[tokio::test] - async fn can_sign_current_epoch_returns_true_when_epoch_service_returns_true() { - let mut services = init_services().await; - - let epoch_service = FakeEpochServiceImpl { - epoch_returned: Epoch(8), - can_signer_sign_current_epoch_returned: Ok(true), - }; - services.epoch_service = Arc::new(RwLock::new(epoch_service)); - - services - .protocol_initializer_store - .save_protocol_initializer(Epoch(7), dummy_protocol_initializer()) - .await - .unwrap(); - - let runner = init_runner(Some(services), None).await; - - assert!(runner.can_sign_current_epoch().await.unwrap()); - } - - #[tokio::test] - async fn can_sign_current_epoch_when_epoch_service_returns_error() { - let mut services = init_services().await; - - let epoch_service = FakeEpochServiceImpl { - epoch_returned: Epoch(8), - can_signer_sign_current_epoch_returned: Err("Simulate an error".to_string()), - }; - services.epoch_service = Arc::new(RwLock::new(epoch_service)); - - services - .protocol_initializer_store - .save_protocol_initializer(Epoch(7), dummy_protocol_initializer()) - .await - .unwrap(); - - let runner = init_runner(Some(services), None).await; - - assert!(runner.can_sign_current_epoch().await.is_err()); - } - - #[tokio::test] - async fn can_sign_current_epoch_returns_false_when_cannot_get_protocol_initializer_for_current_epoch( - ) { - let mut services = init_services().await; - - let epoch_service = FakeEpochServiceImpl { - epoch_returned: Epoch(8), - can_signer_sign_current_epoch_returned: Ok(true), - }; - services.epoch_service = Arc::new(RwLock::new(epoch_service)); - - let runner = init_runner(Some(services), None).await; - - assert!(runner - .services - .protocol_initializer_store - .get_protocol_initializer(Epoch(7)) - .await - .unwrap() - .is_none()); - - assert!(!runner.can_sign_current_epoch().await.unwrap()); - } - #[tokio::test] async fn test_compute_message() { let mut services = init_services().await; diff --git a/mithril-signer/src/services/epoch_service.rs b/mithril-signer/src/services/epoch_service.rs index cfc6720e061..6b3c5b630b3 100644 --- a/mithril-signer/src/services/epoch_service.rs +++ b/mithril-signer/src/services/epoch_service.rs @@ -1,6 +1,6 @@ use anyhow::anyhow; use async_trait::async_trait; -use slog_scope::{debug, trace}; +use slog_scope::{debug, trace, warn}; use std::collections::BTreeSet; use std::sync::Arc; use thiserror::Error; @@ -74,12 +74,8 @@ pub trait EpochService: Sync + Send { &self, ) -> StdResult<&Option>; - /// Check if a signer is included in the current stake distribution - fn is_signer_included_in_current_stake_distribution( - &self, - party_id: PartyId, - protocol_initializer: ProtocolInitializer, - ) -> StdResult; + /// Check if the given signer can sign for the current epoch + fn can_signer_sign_current_epoch(&self, party_id: PartyId) -> StdResult; } struct EpochData { @@ -151,6 +147,17 @@ impl MithrilEpochService { Ok(signers_with_stake) } + fn is_signer_included_in_current_stake_distribution( + &self, + party_id: PartyId, + protocol_initializer: &ProtocolInitializer, + ) -> StdResult { + Ok(self.current_signers()?.iter().any(|s| { + s.party_id == party_id + && s.verification_key == protocol_initializer.verification_key().into() + })) + } + fn unwrap_data(&self) -> Result<&EpochData, EpochServiceError> { self.epoch_data .as_ref() @@ -245,15 +252,22 @@ impl EpochService for MithrilEpochService { Ok(&self.unwrap_data()?.next_cardano_transactions_signing_config) } - fn is_signer_included_in_current_stake_distribution( - &self, - party_id: PartyId, - protocol_initializer: ProtocolInitializer, - ) -> StdResult { - Ok(self.current_signers()?.iter().any(|s| { - s.party_id == party_id - && s.verification_key == protocol_initializer.verification_key().into() - })) + fn can_signer_sign_current_epoch(&self, party_id: PartyId) -> StdResult { + let epoch = self.epoch_of_current_data()?; + if let Some(protocol_initializer) = self.protocol_initializer()? { + debug!(" > got protocol initializer for this epoch ({epoch})"); + if self + .is_signer_included_in_current_stake_distribution(party_id, protocol_initializer)? + { + return Ok(true); + } else { + debug!(" > Signer not in current stake distribution. Can NOT sign"); + } + } else { + warn!(" > NO protocol initializer found for this epoch ({epoch})",); + } + + Ok(false) } } @@ -346,12 +360,7 @@ pub mod mock_epoch_service { &self, ) -> StdResult<&'static Option>; - /// Check if a signer is included in the current stake distribution - fn is_signer_included_in_current_stake_distribution( - &self, - party_id: PartyId, - protocol_initializer: ProtocolInitializer, - ) -> StdResult; + fn can_signer_sign_current_epoch(&self, party_id: PartyId) -> StdResult; } } @@ -383,6 +392,19 @@ mod tests { use super::*; + fn empty_or_default_epoch_data(epoch: Epoch) -> EpochData { + EpochData { + epoch, + next_protocol_parameters: fake_data::protocol_parameters(), + protocol_initializer: None, + current_signers: vec![], + next_signers: vec![], + allowed_discriminants: BTreeSet::new(), + cardano_transactions_signing_config: None, + next_cardano_transactions_signing_config: None, + } + } + #[test] fn test_is_signer_included_in_current_stake_distribution_returns_error_when_epoch_settings_is_not_set( ) { @@ -402,7 +424,7 @@ mod tests { let service = MithrilEpochService::new(stake_store, protocol_initializer_store); service - .is_signer_included_in_current_stake_distribution(party_id, protocol_initializer) + .is_signer_included_in_current_stake_distribution(party_id, &protocol_initializer) .expect_err("can_signer_sign should return error when epoch settings is not set"); } @@ -437,7 +459,7 @@ mod tests { assert!(service .is_signer_included_in_current_stake_distribution( party_id.clone(), - protocol_initializer.clone() + &protocol_initializer ) .unwrap()); @@ -445,7 +467,7 @@ mod tests { assert!(!service .is_signer_included_in_current_stake_distribution( party_id_not_included, - protocol_initializer + &protocol_initializer ) .unwrap()); @@ -455,11 +477,121 @@ mod tests { assert!(!service .is_signer_included_in_current_stake_distribution( party_id, - protocol_initializer_not_included + &protocol_initializer_not_included ) .unwrap()); } + #[test] + fn signer_cant_sign_if_no_protocol_initializer_are_stored() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + + let epoch_service = { + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); + service.epoch_data = Some(EpochData { + protocol_initializer: None, + current_signers: fixtures.signers(), + ..empty_or_default_epoch_data(epoch) + }); + service + }; + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(!can_sign_current_epoch); + } + + #[test] + fn signer_cant_sign_if_it_dont_use_stored_protocol_initializer() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + + let epoch_service = { + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); + service.epoch_data = Some(EpochData { + protocol_initializer: Some( + fixtures.signers_fixture()[2].protocol_initializer.clone(), + ), + current_signers: fixtures.signers(), + ..empty_or_default_epoch_data(epoch) + }); + service + }; + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(!can_sign_current_epoch); + } + + #[test] + fn signer_cant_sign_if_not_in_current_signers() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + + let epoch_service = { + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); + service.epoch_data = Some(EpochData { + protocol_initializer: Some( + fixtures.signers_fixture()[0].protocol_initializer.clone(), + ), + current_signers: fixtures.signers()[2..].to_vec(), + ..empty_or_default_epoch_data(epoch) + }); + service + }; + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(!can_sign_current_epoch); + } + + #[test] + fn signer_can_sign_if_in_current_signers_and_use_the_stored_protocol_initializer() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + + let epoch_service = { + let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); + service.epoch_data = Some(EpochData { + protocol_initializer: Some( + fixtures.signers_fixture()[0].protocol_initializer.clone(), + ), + current_signers: fixtures.signers(), + ..empty_or_default_epoch_data(epoch) + }); + service + }; + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(can_sign_current_epoch); + } + #[tokio::test] async fn test_retrieve_data_return_error_before_register_epoch_settings_was_call() { let epoch = Epoch(12); From d4af2f168562cec2851f4c9c17a2be99f3088c0c Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 12:03:33 +0200 Subject: [PATCH 03/13] refactor: signer `SignableSeedBuilder` compute next avk without SingleSigner This will allow to remove the `compute_aggregate_verification_key` from the signer `MithrilSingleSigner`. --- .../src/dependency_injection/builder.rs | 1 - mithril-signer/src/runtime/runner.rs | 1 - .../signable_builder/signable_seed_builder.rs | 63 ++++++++++--------- .../test_extensions/state_machine_tester.rs | 1 - 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/mithril-signer/src/dependency_injection/builder.rs b/mithril-signer/src/dependency_injection/builder.rs index ba756066331..dfe5d075226 100644 --- a/mithril-signer/src/dependency_injection/builder.rs +++ b/mithril-signer/src/dependency_injection/builder.rs @@ -328,7 +328,6 @@ impl<'a> DependenciesBuilder<'a> { ))); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), - single_signer.clone(), protocol_initializer_store.clone(), )); let signable_builder_service = Arc::new(MithrilSignableBuilderService::new( diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 9267b181ee9..38b9ba43ddf 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -528,7 +528,6 @@ mod tests { let single_signer = Arc::new(MithrilSingleSigner::new(party_id)); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), - single_signer.clone(), protocol_initializer_store.clone(), )); let signable_builder_service = Arc::new(MithrilSignableBuilderService::new( diff --git a/mithril-signer/src/services/signable_builder/signable_seed_builder.rs b/mithril-signer/src/services/signable_builder/signable_seed_builder.rs index 7529816f626..a5cf845e58c 100644 --- a/mithril-signer/src/services/signable_builder/signable_seed_builder.rs +++ b/mithril-signer/src/services/signable_builder/signable_seed_builder.rs @@ -3,26 +3,24 @@ //! This service is responsible for computing the seed protocol message //! that is used by the [SignableBuilder] to compute the final protocol message. //! -use anyhow::anyhow; +use anyhow::{anyhow, Context}; use async_trait::async_trait; use std::sync::Arc; use tokio::sync::RwLock; use mithril_common::{ - entities::{ProtocolMessagePartValue, ProtocolParameters}, + crypto_helper::ProtocolInitializer, + entities::{ProtocolMessagePartValue, ProtocolParameters, SignerWithStake}, + protocol::SignerBuilder, signable_builder::SignableSeedBuilder, StdResult, }; -use crate::{ - services::{EpochService, SingleSigner}, - store::ProtocolInitializerStorer, -}; +use crate::{services::EpochService, store::ProtocolInitializerStorer}; /// SignableSeedBuilder signer implementation pub struct SignerSignableSeedBuilder { epoch_service: Arc>, - single_signer: Arc, protocol_initializer_store: Arc, } @@ -30,15 +28,34 @@ impl SignerSignableSeedBuilder { /// SignerSignableSeedBuilder factory pub fn new( epoch_service: Arc>, - single_signer: Arc, protocol_initializer_store: Arc, ) -> Self { Self { epoch_service, - single_signer, protocol_initializer_store, } } + + fn compute_encode_avk( + &self, + protocol_initializer: ProtocolInitializer, + signers_with_stake: &[SignerWithStake], + ) -> StdResult { + let signer_builder = SignerBuilder::new( + signers_with_stake, + &protocol_initializer.get_protocol_parameters().into(), + ) + .with_context(|| "SignerSignableSeedBuilder can not compute aggregate verification key")?; + + let encoded_avk = signer_builder + .compute_aggregate_verification_key() + .to_json_hex() + .with_context(|| { + "SignerSignableSeedBuilder can not serialize aggregate verification key" + })?; + + Ok(encoded_avk) + } } #[async_trait] @@ -55,13 +72,8 @@ impl SignableSeedBuilder for SignerSignableSeedBuilder { anyhow!("can not get protocol_initializer at epoch {next_signer_retrieval_epoch}") })?; let next_signers_with_stake = epoch_service.next_signers_with_stake().await?; - let next_aggregate_verification_key = self - .single_signer - .compute_aggregate_verification_key( - &next_signers_with_stake, - &next_protocol_initializer, - )? - .ok_or_else(|| anyhow!("next_signers avk".to_string()))?; + let next_aggregate_verification_key = + self.compute_encode_avk(next_protocol_initializer, &next_signers_with_stake)?; Ok(next_aggregate_verification_key) } @@ -99,15 +111,13 @@ mod tests { }; use crate::{ - services::{mock_epoch_service::MockEpochServiceImpl, MockSingleSigner}, - store::MockProtocolInitializerStorer, + services::mock_epoch_service::MockEpochServiceImpl, store::MockProtocolInitializerStorer, }; use super::*; struct MockDependencyInjector { mock_epoch_service: MockEpochServiceImpl, - mock_single_signer: MockSingleSigner, mock_protocol_initializer_store: MockProtocolInitializerStorer, } @@ -115,7 +125,6 @@ mod tests { fn new() -> MockDependencyInjector { MockDependencyInjector { mock_epoch_service: MockEpochServiceImpl::new(), - mock_single_signer: MockSingleSigner::new(), mock_protocol_initializer_store: MockProtocolInitializerStorer::new(), } } @@ -123,7 +132,6 @@ mod tests { fn build_signable_builder_service(self) -> SignerSignableSeedBuilder { SignerSignableSeedBuilder::new( Arc::new(RwLock::new(self.mock_epoch_service)), - Arc::new(self.mock_single_signer), Arc::new(self.mock_protocol_initializer_store), ) } @@ -136,9 +144,7 @@ mod tests { let protocol_initializer = next_fixture.signers_fixture()[0] .protocol_initializer .clone(); - let expected_next_aggregate_verification_key = next_fixture.compute_and_encode_avk(); - let expected_next_aggregate_verification_key_clone = - expected_next_aggregate_verification_key.clone(); + let next_signers_with_stake = next_fixture.signers_with_stake(); let mut mock_container = MockDependencyInjector::new(); mock_container.mock_epoch_service = MockEpochServiceImpl::new_with_config(|mock_epoch_service| { @@ -148,14 +154,9 @@ mod tests { .once(); mock_epoch_service .expect_next_signers_with_stake() - .return_once(|| Ok(Vec::new())) + .return_once(move || Ok(next_signers_with_stake)) .once(); }); - mock_container - .mock_single_signer - .expect_compute_aggregate_verification_key() - .return_once(move |_, _| Ok(Some(expected_next_aggregate_verification_key_clone))) - .once(); mock_container .mock_protocol_initializer_store .expect_get_protocol_initializer() @@ -170,7 +171,7 @@ mod tests { assert_eq!( next_aggregate_verification_key, - expected_next_aggregate_verification_key + next_fixture.compute_and_encode_avk() ); } diff --git a/mithril-signer/tests/test_extensions/state_machine_tester.rs b/mithril-signer/tests/test_extensions/state_machine_tester.rs index dd9ca6926de..06d17a09caa 100644 --- a/mithril-signer/tests/test_extensions/state_machine_tester.rs +++ b/mithril-signer/tests/test_extensions/state_machine_tester.rs @@ -222,7 +222,6 @@ impl StateMachineTester { ))); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), - single_signer.clone(), protocol_initializer_store.clone(), )); let signable_builder_service = Arc::new(MithrilSignableBuilderService::new( From 747bcd49022b5f6878af047719633c747fc73953 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:38:41 +0200 Subject: [PATCH 04/13] refactor: remove `compute_aggregate_verification_key` from signer SingleSigner Has the signable seed service, its only business usage, doesn't need it anymore. --- mithril-signer/src/runtime/runner.rs | 79 +------------------- mithril-signer/src/services/single_signer.rs | 47 ------------ 2 files changed, 1 insertion(+), 125 deletions(-) diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 38b9ba43ddf..357c2fc0805 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -410,8 +410,7 @@ mod tests { }, digesters::{DumbImmutableDigester, DumbImmutableFileObserver}, entities::{ - BlockNumber, BlockRange, CardanoDbBeacon, Epoch, ProtocolMessagePartKey, - SignedEntityTypeDiscriminants, + BlockNumber, BlockRange, Epoch, ProtocolMessagePartKey, SignedEntityTypeDiscriminants, }, era::{adapters::EraReaderBootstrapAdapter, EraChecker, EraReader}, messages::{AggregatorCapabilities, AggregatorFeaturesMessage}, @@ -693,82 +692,6 @@ mod tests { ); } - #[tokio::test] - async fn test_compute_message() { - let mut services = init_services().await; - let current_time_point = services - .ticker_service - .get_current_time_point() - .await - .expect("get_current_time_point should not fail"); - let signed_entity_type = SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new( - "whatever", - *current_time_point.epoch, - current_time_point.immutable_file_number, - )); - let fixture = MithrilFixtureBuilder::default().with_signers(5).build(); - let signer_with_stake = fixture.signers_fixture()[0].signer_with_stake.clone(); - let protocol_initializer = fixture.signers_fixture()[0].protocol_initializer.clone(); - let single_signer = Arc::new(MithrilSingleSigner::new( - signer_with_stake.party_id.to_owned(), - )); - services.single_signer = single_signer.clone(); - services - .protocol_initializer_store - .save_protocol_initializer( - current_time_point - .epoch - .offset_to_next_signer_retrieval_epoch(), - protocol_initializer.clone(), - ) - .await - .expect("save_protocol_initializer should not fail"); - - services - .stake_store - .save_stakes( - current_time_point - .epoch - .offset_to_next_signer_retrieval_epoch(), - fixture.stake_distribution(), - ) - .await - .expect("save_stakes should not fail"); - - let next_signers_with_stake = &fixture.signers_with_stake()[3..5]; - let next_signers = &fixture.signers()[3..5]; - - let mut expected = ProtocolMessage::new(); - expected.set_message_part( - ProtocolMessagePartKey::SnapshotDigest, - DIGESTER_RESULT.to_string(), - ); - let avk = services - .single_signer - .compute_aggregate_verification_key(next_signers_with_stake, &protocol_initializer) - .expect("compute_aggregate_verification_key should not fail") - .expect("an avk should have been computed"); - expected.set_message_part(ProtocolMessagePartKey::NextAggregateVerificationKey, avk); - - let runner = init_runner(Some(services), None).await; - - // inform epoch settings - let epoch_settings = SignerEpochSettings { - epoch: current_time_point.epoch, - current_signers: fixture.signers(), - next_signers: next_signers.to_vec(), - ..SignerEpochSettings::dummy().clone() - }; - runner.inform_epoch_settings(epoch_settings).await.unwrap(); - - let message = runner - .compute_message(&signed_entity_type) - .await - .expect("compute_message should not fail"); - - assert_eq!(expected, message); - } - #[tokio::test] async fn test_compute_single_signature() { let mut services = init_services().await; diff --git a/mithril-signer/src/services/single_signer.rs b/mithril-signer/src/services/single_signer.rs index 06b7e03c85d..8c2bf87d56c 100644 --- a/mithril-signer/src/services/single_signer.rs +++ b/mithril-signer/src/services/single_signer.rs @@ -49,13 +49,6 @@ pub trait SingleSigner: Sync + Send { protocol_initializer: &ProtocolInitializer, ) -> StdResult>; - /// Compute aggregate verification key from stake distribution - fn compute_aggregate_verification_key( - &self, - signers_with_stake: &[SignerWithStake], - protocol_initializer: &ProtocolInitializer, - ) -> StdResult>; - /// Get party id fn get_party_id(&self) -> PartyId; } @@ -136,29 +129,6 @@ impl SingleSigner for MithrilSingleSigner { Ok(signatures) } - /// Compute aggregate verification key from stake distribution - fn compute_aggregate_verification_key( - &self, - signers_with_stake: &[SignerWithStake], - protocol_initializer: &ProtocolInitializer, - ) -> StdResult> { - let signer_builder = SignerBuilder::new( - signers_with_stake, - &protocol_initializer.get_protocol_parameters().into(), - ) - .with_context(|| "Mithril Single Signer can not compute aggregate verification key") - .map_err(SingleSignerError::AggregateVerificationKeyComputationFailed)?; - - let encoded_avk = signer_builder - .compute_aggregate_verification_key() - .to_json_hex() - .with_context(|| { - "Mithril Single Signer can not serialize aggregate verification key" - })?; - - Ok(Some(encoded_avk)) - } - /// Get party id fn get_party_id(&self) -> PartyId { self.party_id.clone() @@ -210,21 +180,4 @@ mod tests { "produced single signature should be valid" ); } - - #[test] - fn compute_aggregate_verification_key_success() { - let fixture = MithrilFixtureBuilder::default().with_signers(5).build(); - let signers_with_stake = fixture.signers_with_stake(); - let current_signer = &fixture.signers_fixture()[0]; - let single_signer = - MithrilSingleSigner::new(current_signer.signer_with_stake.party_id.to_owned()); - - single_signer - .compute_aggregate_verification_key( - &signers_with_stake, - ¤t_signer.protocol_initializer, - ) - .expect("compute aggregate verification signature should not fail") - .expect("aggregate verification signature should not be empty"); - } } From 92788abc4749b360700f26595e3f4cc5dfd74ed8 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:50:33 +0200 Subject: [PATCH 05/13] test: add tooling to make tests using signer epoch service easier --- mithril-signer/src/services/epoch_service.rs | 137 +++++++++++-------- 1 file changed, 77 insertions(+), 60 deletions(-) diff --git a/mithril-signer/src/services/epoch_service.rs b/mithril-signer/src/services/epoch_service.rs index 6b3c5b630b3..1c9bc69e669 100644 --- a/mithril-signer/src/services/epoch_service.rs +++ b/mithril-signer/src/services/epoch_service.rs @@ -78,15 +78,15 @@ pub trait EpochService: Sync + Send { fn can_signer_sign_current_epoch(&self, party_id: PartyId) -> StdResult; } -struct EpochData { - epoch: Epoch, - next_protocol_parameters: ProtocolParameters, - protocol_initializer: Option, - current_signers: Vec, - next_signers: Vec, - allowed_discriminants: BTreeSet, - cardano_transactions_signing_config: Option, - next_cardano_transactions_signing_config: Option, +pub(crate) struct EpochData { + pub epoch: Epoch, + pub next_protocol_parameters: ProtocolParameters, + pub protocol_initializer: Option, + pub current_signers: Vec, + pub next_signers: Vec, + pub allowed_discriminants: BTreeSet, + pub cardano_transactions_signing_config: Option, + pub next_cardano_transactions_signing_config: Option, } /// Implementation of the [epoch service][EpochService]. @@ -308,6 +308,51 @@ impl SignedEntityConfigProvider for SignerSignedEntityConfigProvider { } } +#[cfg(test)] +impl MithrilEpochService { + /// `TEST ONLY` - Create a new instance of the service using dumb dependencies. + pub fn new_with_dumb_dependencies() -> Self { + use crate::store::ProtocolInitializerStore; + use mithril_persistence::store::adapter::DumbStoreAdapter; + use mithril_persistence::store::StakeStore; + + let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + + Self::new(stake_store, protocol_initializer_store) + } + + /// `TEST ONLY` - Set all data to either default values, empty values, or fake values + /// if no default/empty can be set. + pub fn set_data_to_default_or_fake(mut self, epoch: Epoch) -> Self { + use mithril_common::test_utils::fake_data; + + let epoch_data = EpochData { + epoch, + next_protocol_parameters: fake_data::protocol_parameters(), + protocol_initializer: None, + current_signers: vec![], + next_signers: vec![], + allowed_discriminants: BTreeSet::new(), + cardano_transactions_signing_config: None, + next_cardano_transactions_signing_config: None, + }; + self.epoch_data = Some(epoch_data); + self + } + + /// `TEST ONLY` - Alter the data stored in the service, won't do anything if no data is stored. + pub(crate) fn alter_data(mut self, data_config: impl FnOnce(&mut EpochData)) -> Self { + if let Some(data) = self.epoch_data.as_mut() { + data_config(data); + } + self + } +} + #[cfg(test)] pub mod mock_epoch_service { use mockall::mock; @@ -392,19 +437,6 @@ mod tests { use super::*; - fn empty_or_default_epoch_data(epoch: Epoch) -> EpochData { - EpochData { - epoch, - next_protocol_parameters: fake_data::protocol_parameters(), - protocol_initializer: None, - current_signers: vec![], - next_signers: vec![], - allowed_discriminants: BTreeSet::new(), - cardano_transactions_signing_config: None, - next_cardano_transactions_signing_config: None, - } - } - #[test] fn test_is_signer_included_in_current_stake_distribution_returns_error_when_epoch_settings_is_not_set( ) { @@ -492,15 +524,12 @@ mod tests { None, )); - let epoch_service = { - let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); - service.epoch_data = Some(EpochData { - protocol_initializer: None, - current_signers: fixtures.signers(), - ..empty_or_default_epoch_data(epoch) + let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = None; + data.current_signers = fixtures.signers(); }); - service - }; let can_sign_current_epoch = epoch_service .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) @@ -518,17 +547,13 @@ mod tests { None, )); - let epoch_service = { - let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); - service.epoch_data = Some(EpochData { - protocol_initializer: Some( - fixtures.signers_fixture()[2].protocol_initializer.clone(), - ), - current_signers: fixtures.signers(), - ..empty_or_default_epoch_data(epoch) + let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = + Some(fixtures.signers_fixture()[2].protocol_initializer.clone()); + data.current_signers = fixtures.signers(); }); - service - }; let can_sign_current_epoch = epoch_service .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) @@ -546,17 +571,13 @@ mod tests { None, )); - let epoch_service = { - let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); - service.epoch_data = Some(EpochData { - protocol_initializer: Some( - fixtures.signers_fixture()[0].protocol_initializer.clone(), - ), - current_signers: fixtures.signers()[2..].to_vec(), - ..empty_or_default_epoch_data(epoch) + let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = + Some(fixtures.signers_fixture()[0].protocol_initializer.clone()); + data.current_signers = fixtures.signers()[2..].to_vec(); }); - service - }; let can_sign_current_epoch = epoch_service .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) @@ -574,17 +595,13 @@ mod tests { None, )); - let epoch_service = { - let mut service = MithrilEpochService::new(stake_store, protocol_initializer_store); - service.epoch_data = Some(EpochData { - protocol_initializer: Some( - fixtures.signers_fixture()[0].protocol_initializer.clone(), - ), - current_signers: fixtures.signers(), - ..empty_or_default_epoch_data(epoch) + let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = + Some(fixtures.signers_fixture()[0].protocol_initializer.clone()); + data.current_signers = fixtures.signers(); }); - service - }; let can_sign_current_epoch = epoch_service .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) From fdf1ab2dd5866870cb1de1fe8f1465437f6ff871 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:53:53 +0200 Subject: [PATCH 06/13] refactor: simplify signer SingleSigner signature computation By using the `protocol_initializer` stored in the epoch service, removing the need to pass it in `compute_single_signatures` parameters. --- .../src/dependency_injection/builder.rs | 5 +- mithril-signer/src/runtime/runner.rs | 36 ++++------ mithril-signer/src/runtime/state_machine.rs | 4 +- mithril-signer/src/services/single_signer.rs | 71 ++++++++++++------- .../test_extensions/state_machine_tester.rs | 7 +- 5 files changed, 70 insertions(+), 53 deletions(-) diff --git a/mithril-signer/src/dependency_injection/builder.rs b/mithril-signer/src/dependency_injection/builder.rs index dfe5d075226..8c533a67460 100644 --- a/mithril-signer/src/dependency_injection/builder.rs +++ b/mithril-signer/src/dependency_injection/builder.rs @@ -214,7 +214,6 @@ impl<'a> DependenciesBuilder<'a> { )?), self.config.store_retention_limit, )); - let single_signer = Arc::new(MithrilSingleSigner::new(self.compute_protocol_party_id()?)); let digester = Arc::new(CardanoImmutableDigester::new( self.build_digester_cache_provider().await?, slog_scope::logger(), @@ -326,6 +325,10 @@ impl<'a> DependenciesBuilder<'a> { stake_store.clone(), protocol_initializer_store.clone(), ))); + let single_signer = Arc::new(MithrilSingleSigner::new( + self.compute_protocol_party_id()?, + epoch_service.clone(), + )); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), protocol_initializer_store.clone(), diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 357c2fc0805..0c36060eaa1 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -50,7 +50,6 @@ pub trait Runner: Send + Sync { /// Create the single signature. async fn compute_single_signature( &self, - epoch: Epoch, message: &ProtocolMessage, ) -> StdResult>; @@ -288,7 +287,6 @@ impl Runner for SignerRunner { async fn compute_single_signature( &self, - epoch: Epoch, message: &ProtocolMessage, ) -> StdResult> { debug!("RUNNER: compute_single_signature"); @@ -298,22 +296,11 @@ impl Runner for SignerRunner { .await .with_context(|| "Runner can not not retrieve signers")?; - let signer_retrieval_epoch = epoch.offset_to_signer_retrieval_epoch()?; - let protocol_initializer = self + let signature = self .services - .protocol_initializer_store - .get_protocol_initializer(signer_retrieval_epoch) - .await? - .ok_or_else(|| { - RunnerError::NoValueError(format!( - "protocol_initializer at epoch {signer_retrieval_epoch}" - )) - })?; - let signature = self.services.single_signer.compute_single_signatures( - message, - &signers, - &protocol_initializer, - )?; + .single_signer + .compute_single_signatures(message, &signers) + .await?; info!( " > {}", if signature.is_some() { @@ -524,7 +511,7 @@ mod tests { stake_store.clone(), protocol_initializer_store.clone(), ))); - let single_signer = Arc::new(MithrilSingleSigner::new(party_id)); + let single_signer = Arc::new(MithrilSingleSigner::new(party_id, epoch_service.clone())); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), protocol_initializer_store.clone(), @@ -703,8 +690,10 @@ mod tests { let fixture = MithrilFixtureBuilder::default().with_signers(5).build(); let signer_with_stake = fixture.signers_fixture()[0].signer_with_stake.clone(); let protocol_initializer = fixture.signers_fixture()[0].protocol_initializer.clone(); + let single_signer = Arc::new(MithrilSingleSigner::new( signer_with_stake.party_id.to_string(), + services.epoch_service.clone(), )); services.single_signer = single_signer.clone(); services @@ -744,10 +733,6 @@ mod tests { "an avk".to_string(), ); - let expected = single_signer - .compute_single_signatures(&message, signers_with_stake, &protocol_initializer) - .expect("compute_single_signatures should not fail"); - let runner = init_runner(Some(services), None).await; // inform epoch settings @@ -759,8 +744,13 @@ mod tests { }; runner.inform_epoch_settings(epoch_settings).await.unwrap(); + let expected = single_signer + .compute_single_signatures(&message, signers_with_stake) + .await + .expect("compute_single_signatures should not fail"); + let single_signature = runner - .compute_single_signature(current_time_point.epoch, &message) + .compute_single_signature(&message) .await .expect("compute_message should not fail"); assert_eq!(expected, single_signature); diff --git a/mithril-signer/src/runtime/state_machine.rs b/mithril-signer/src/runtime/state_machine.rs index 9e2190bdd12..6d995c3889d 100644 --- a/mithril-signer/src/runtime/state_machine.rs +++ b/mithril-signer/src/runtime/state_machine.rs @@ -377,7 +377,7 @@ impl StateMachine { let single_signatures = self .runner - .compute_single_signature(current_epoch, &message) + .compute_single_signature(&message) .await .map_err(|e| RuntimeError::KeepState { message: format!("Could not compute single signature during 'ready to sign → ready to sign' phase (current epoch {current_epoch:?})"), @@ -725,7 +725,7 @@ mod tests { runner .expect_compute_single_signature() .once() - .returning(|_, _| Ok(Some(fake_data::single_signatures(vec![1, 5, 23])))); + .returning(|_| Ok(Some(fake_data::single_signatures(vec![1, 5, 23])))); runner .expect_compute_message() .once() diff --git a/mithril-signer/src/services/single_signer.rs b/mithril-signer/src/services/single_signer.rs index 8c2bf87d56c..fe8097e9b79 100644 --- a/mithril-signer/src/services/single_signer.rs +++ b/mithril-signer/src/services/single_signer.rs @@ -1,4 +1,5 @@ use anyhow::{anyhow, Context}; +use async_trait::async_trait; use hex::ToHex; use slog_scope::{info, trace, warn}; use std::path::PathBuf; @@ -11,10 +12,9 @@ use mithril_common::entities::{ use mithril_common::protocol::SignerBuilder; use mithril_common::{StdError, StdResult}; -#[cfg(test)] -use mockall::automock; +use crate::dependency_injection::EpochServiceWrapper; -/// This is responsible of creating new instances of ProtocolInitializer. +/// This is responsible for creating new instances of ProtocolInitializer. pub struct MithrilProtocolInitializerBuilder {} impl MithrilProtocolInitializerBuilder { @@ -38,15 +38,15 @@ impl MithrilProtocolInitializerBuilder { } } -/// The SingleSigner is the structure responsible of issuing SingleSignatures. -#[cfg_attr(test, automock)] +/// The SingleSigner is the structure responsible for issuing SingleSignatures. +#[cfg_attr(test, mockall::automock)] +#[async_trait] pub trait SingleSigner: Sync + Send { /// Computes single signatures - fn compute_single_signatures( + async fn compute_single_signatures( &self, protocol_message: &ProtocolMessage, signers_with_stake: &[SignerWithStake], - protocol_initializer: &ProtocolInitializer, ) -> StdResult>; /// Get party id @@ -72,22 +72,35 @@ pub enum SingleSignerError { /// Implementation of the SingleSigner. pub struct MithrilSingleSigner { party_id: PartyId, + epoch_service: EpochServiceWrapper, } impl MithrilSingleSigner { /// Create a new instance of the MithrilSingleSigner. - pub fn new(party_id: PartyId) -> Self { - Self { party_id } + pub fn new(party_id: PartyId, epoch_service: EpochServiceWrapper) -> Self { + Self { + party_id, + epoch_service, + } + } + + async fn get_protocol_initializer(&self) -> StdResult { + let epoch_service = self.epoch_service.read().await; + epoch_service.protocol_initializer()?.clone().ok_or(anyhow!( + "Can not Sign or Compute AVK, No protocol initializer found for party_id: '{}'", + self.party_id.clone() + )) } } +#[async_trait] impl SingleSigner for MithrilSingleSigner { - fn compute_single_signatures( + async fn compute_single_signatures( &self, protocol_message: &ProtocolMessage, signers_with_stake: &[SignerWithStake], - protocol_initializer: &ProtocolInitializer, ) -> StdResult> { + let protocol_initializer = self.get_protocol_initializer().await?; let builder = SignerBuilder::new( signers_with_stake, &protocol_initializer.get_protocol_parameters().into(), @@ -137,32 +150,42 @@ impl SingleSigner for MithrilSingleSigner { #[cfg(test)] mod tests { - use super::*; + use std::sync::Arc; + use tokio::sync::RwLock; - use mithril_common::{ - crypto_helper::ProtocolClerk, entities::ProtocolMessagePartKey, - test_utils::MithrilFixtureBuilder, - }; + use mithril_common::crypto_helper::ProtocolClerk; + use mithril_common::entities::{Epoch, ProtocolMessagePartKey}; + use mithril_common::test_utils::MithrilFixtureBuilder; - #[test] - fn compute_single_signature_success() { + use crate::services::MithrilEpochService; + + use super::*; + + #[tokio::test] + async fn compute_single_signature_success() { let snapshot_digest = "digest".to_string(); let fixture = MithrilFixtureBuilder::default().with_signers(5).build(); let signers_with_stake = fixture.signers_with_stake(); let current_signer = &fixture.signers_fixture()[0]; - let single_signer = MithrilSingleSigner::new(current_signer.party_id()); let clerk = ProtocolClerk::from_signer(¤t_signer.protocol_signer); let avk = clerk.compute_avk(); let mut protocol_message = ProtocolMessage::new(); protocol_message.set_message_part(ProtocolMessagePartKey::SnapshotDigest, snapshot_digest); let expected_message = protocol_message.compute_hash().as_bytes().to_vec(); + let epoch_service = MithrilEpochService::new_with_dumb_dependencies() + .set_data_to_default_or_fake(Epoch(10)) + .alter_data(|data| { + data.protocol_initializer = Some(current_signer.protocol_initializer.clone()) + }); + + let single_signer = MithrilSingleSigner::new( + current_signer.party_id(), + Arc::new(RwLock::new(epoch_service)), + ); let sign_result = single_signer - .compute_single_signatures( - &protocol_message, - &signers_with_stake, - ¤t_signer.protocol_initializer, - ) + .compute_single_signatures(&protocol_message, &signers_with_stake) + .await .expect("single signer should not fail") .expect("single signer should produce a signature here"); diff --git a/mithril-signer/tests/test_extensions/state_machine_tester.rs b/mithril-signer/tests/test_extensions/state_machine_tester.rs index 06d17a09caa..6249f2ff25a 100644 --- a/mithril-signer/tests/test_extensions/state_machine_tester.rs +++ b/mithril-signer/tests/test_extensions/state_machine_tester.rs @@ -163,9 +163,6 @@ impl StateMachineTester { ), config.store_retention_limit, )); - let single_signer = Arc::new(MithrilSingleSigner::new( - config.party_id.to_owned().unwrap_or_default(), - )); let stake_store = Arc::new(StakeStore::new( Box::new(SQLiteAdapter::new("stake", sqlite_connection.clone()).unwrap()), config.store_retention_limit, @@ -220,6 +217,10 @@ impl StateMachineTester { stake_store.clone(), protocol_initializer_store.clone(), ))); + let single_signer = Arc::new(MithrilSingleSigner::new( + config.party_id.to_owned().unwrap_or_default(), + epoch_service.clone(), + )); let signable_seed_builder_service = Arc::new(SignerSignableSeedBuilder::new( epoch_service.clone(), protocol_initializer_store.clone(), From 8a2b36e473a837704be10e8f4f4a60874543591a Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:40:12 +0200 Subject: [PATCH 07/13] refactor: simplify signer SingleSigner signature computation By using the `current_signers_with_stake` of the epoch service, removing the need to pass it in `compute_single_signatures` parameters. --- mithril-signer/src/runtime/runner.rs | 20 +---- mithril-signer/src/services/single_signer.rs | 85 +++++++++++++------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 0c36060eaa1..80f18fe441f 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -6,8 +6,7 @@ use tokio::sync::RwLockReadGuard; use mithril_common::crypto_helper::{KESPeriod, OpCert, ProtocolOpCert, SerDeShelleyFileFormat}; use mithril_common::entities::{ - Epoch, PartyId, ProtocolMessage, SignedEntityType, Signer, SignerWithStake, SingleSignatures, - TimePoint, + Epoch, PartyId, ProtocolMessage, SignedEntityType, Signer, SingleSignatures, TimePoint, }; use mithril_common::StdResult; use mithril_persistence::store::StakeStorer; @@ -100,13 +99,6 @@ impl SignerRunner { Self { services, config } } - /// Get the current signers with their stake. - async fn get_current_signers_with_stake(&self) -> StdResult> { - let epoch_service = self.epoch_service_read().await; - - epoch_service.current_signers_with_stake().await - } - async fn epoch_service_read(&self) -> RwLockReadGuard<'_, dyn EpochService> { self.services.epoch_service.read().await } @@ -291,15 +283,10 @@ impl Runner for SignerRunner { ) -> StdResult> { debug!("RUNNER: compute_single_signature"); - let signers = self - .get_current_signers_with_stake() - .await - .with_context(|| "Runner can not not retrieve signers")?; - let signature = self .services .single_signer - .compute_single_signatures(message, &signers) + .compute_single_signatures(message) .await?; info!( " > {}", @@ -720,7 +707,6 @@ mod tests { .await .expect("save_stakes should not fail"); - let signers_with_stake = &fixture.signers_with_stake()[0..3]; let signers = &fixture.signers()[0..3]; let mut message = ProtocolMessage::new(); @@ -745,7 +731,7 @@ mod tests { runner.inform_epoch_settings(epoch_settings).await.unwrap(); let expected = single_signer - .compute_single_signatures(&message, signers_with_stake) + .compute_single_signatures(&message) .await .expect("compute_single_signatures should not fail"); diff --git a/mithril-signer/src/services/single_signer.rs b/mithril-signer/src/services/single_signer.rs index fe8097e9b79..f28521f0fca 100644 --- a/mithril-signer/src/services/single_signer.rs +++ b/mithril-signer/src/services/single_signer.rs @@ -7,9 +7,9 @@ use thiserror::Error; use mithril_common::crypto_helper::{KESPeriod, ProtocolInitializer}; use mithril_common::entities::{ - PartyId, ProtocolMessage, ProtocolParameters, SignerWithStake, SingleSignatures, Stake, + PartyId, ProtocolMessage, ProtocolParameters, SingleSignatures, Stake, }; -use mithril_common::protocol::SignerBuilder; +use mithril_common::protocol::{SignerBuilder, SingleSigner as ProtocolSingleSigner}; use mithril_common::{StdError, StdResult}; use crate::dependency_injection::EpochServiceWrapper; @@ -46,7 +46,6 @@ pub trait SingleSigner: Sync + Send { async fn compute_single_signatures( &self, protocol_message: &ProtocolMessage, - signers_with_stake: &[SignerWithStake], ) -> StdResult>; /// Get party id @@ -84,31 +83,25 @@ impl MithrilSingleSigner { } } - async fn get_protocol_initializer(&self) -> StdResult { + async fn build_protocol_single_signer(&self) -> StdResult { let epoch_service = self.epoch_service.read().await; - epoch_service.protocol_initializer()?.clone().ok_or(anyhow!( - "Can not Sign or Compute AVK, No protocol initializer found for party_id: '{}'", - self.party_id.clone() - )) - } -} + let protocol_initializer = + epoch_service + .protocol_initializer()? + .as_ref() + .ok_or(anyhow!( + "Can not Sign or Compute AVK, No protocol initializer found for party_id: '{}'", + self.party_id.clone() + ))?; -#[async_trait] -impl SingleSigner for MithrilSingleSigner { - async fn compute_single_signatures( - &self, - protocol_message: &ProtocolMessage, - signers_with_stake: &[SignerWithStake], - ) -> StdResult> { - let protocol_initializer = self.get_protocol_initializer().await?; let builder = SignerBuilder::new( - signers_with_stake, + &epoch_service.current_signers_with_stake().await?, &protocol_initializer.get_protocol_parameters().into(), ) .with_context(|| "Mithril Single Signer can not build signer") - .map_err(|e| SingleSignerError::ProtocolSignerCreationFailure(anyhow!(e)))?; - info!("Signing protocol message"; "protocol_message" => #?protocol_message, "signed message" => protocol_message.compute_hash().encode_hex::()); - let signatures = builder + .map_err(SingleSignerError::ProtocolSignerCreationFailure)?; + + let single_signer = builder .restore_signer_from_initializer(self.party_id.clone(), protocol_initializer.clone()) .with_context(|| { format!( @@ -116,7 +109,22 @@ impl SingleSigner for MithrilSingleSigner { self.party_id.clone() ) }) - .map_err(|e| SingleSignerError::ProtocolSignerCreationFailure(anyhow!(e)))? + .map_err(SingleSignerError::ProtocolSignerCreationFailure)?; + + Ok(single_signer) + } +} + +#[async_trait] +impl SingleSigner for MithrilSingleSigner { + async fn compute_single_signatures( + &self, + protocol_message: &ProtocolMessage, + ) -> StdResult> { + let protocol_single_signer = self.build_protocol_single_signer().await?; + + info!("Signing protocol message"; "protocol_message" => #?protocol_message, "signed message" => protocol_message.compute_hash().encode_hex::()); + let signatures = protocol_single_signer .sign(protocol_message) .with_context(|| { format!( @@ -156,8 +164,11 @@ mod tests { use mithril_common::crypto_helper::ProtocolClerk; use mithril_common::entities::{Epoch, ProtocolMessagePartKey}; use mithril_common::test_utils::MithrilFixtureBuilder; + use mithril_persistence::store::adapter::{DumbStoreAdapter, MemoryAdapter}; + use mithril_persistence::store::StakeStore; use crate::services::MithrilEpochService; + use crate::store::ProtocolInitializerStore; use super::*; @@ -165,17 +176,28 @@ mod tests { async fn compute_single_signature_success() { let snapshot_digest = "digest".to_string(); let fixture = MithrilFixtureBuilder::default().with_signers(5).build(); - let signers_with_stake = fixture.signers_with_stake(); let current_signer = &fixture.signers_fixture()[0]; let clerk = ProtocolClerk::from_signer(¤t_signer.protocol_signer); let avk = clerk.compute_avk(); - let mut protocol_message = ProtocolMessage::new(); - protocol_message.set_message_part(ProtocolMessagePartKey::SnapshotDigest, snapshot_digest); - let expected_message = protocol_message.compute_hash().as_bytes().to_vec(); - let epoch_service = MithrilEpochService::new_with_dumb_dependencies() + let stake_store = Arc::new(StakeStore::new( + Box::new( + MemoryAdapter::new(Some(vec![( + Epoch(10).offset_to_signer_retrieval_epoch().unwrap(), + fixture.stake_distribution(), + )])) + .unwrap(), + ), + None, + )); + let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( + Box::new(DumbStoreAdapter::new()), + None, + )); + let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) .set_data_to_default_or_fake(Epoch(10)) .alter_data(|data| { - data.protocol_initializer = Some(current_signer.protocol_initializer.clone()) + data.protocol_initializer = Some(current_signer.protocol_initializer.clone()); + data.current_signers = fixture.signers(); }); let single_signer = MithrilSingleSigner::new( @@ -183,12 +205,15 @@ mod tests { Arc::new(RwLock::new(epoch_service)), ); + let mut protocol_message = ProtocolMessage::new(); + protocol_message.set_message_part(ProtocolMessagePartKey::SnapshotDigest, snapshot_digest); let sign_result = single_signer - .compute_single_signatures(&protocol_message, &signers_with_stake) + .compute_single_signatures(&protocol_message) .await .expect("single signer should not fail") .expect("single signer should produce a signature here"); + let expected_message = protocol_message.compute_hash().as_bytes().to_vec(); let decoded_sig = sign_result.to_protocol_signature(); assert!( decoded_sig From f28f383e962d4162c7516fdf75d1cc90b9b90897 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:37:54 +0200 Subject: [PATCH 08/13] tests: simplify dependencies in signer certifier tests By allowing to only specifies the dependencies that matters for the test. --- mithril-signer/src/services/certifier.rs | 82 ++++++++++++------------ 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/mithril-signer/src/services/certifier.rs b/mithril-signer/src/services/certifier.rs index f7efec8907d..06b2e7977ec 100644 --- a/mithril-signer/src/services/certifier.rs +++ b/mithril-signer/src/services/certifier.rs @@ -131,15 +131,14 @@ mod tests { for signed_entity_type in SignedEntityTypeDiscriminants::all() { locker.lock(signed_entity_type).await; } - let certifier_service = SignerCertifierService::new( - Arc::new(DumbTickerService::new(TimePoint::dummy())), - Arc::new(DumbSignedBeaconStore::default()), - Arc::new(DumbSignedEntityConfigProvider::new( + let certifier_service = SignerCertifierService { + signed_entity_type_lock: locker.clone(), + signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), )), - locker, - ); + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; let beacon_to_sign = certifier_service.get_beacon_to_sign().await.unwrap(); assert_eq!(beacon_to_sign, None); @@ -147,20 +146,18 @@ mod tests { #[tokio::test] async fn only_one_unlocked_and_not_yet_signed_yield_a_beacon_to_sign() { - let ticker_service = DumbTickerService::new(TimePoint::new(3, 14, ChainPoint::dummy())); let locker = Arc::new(SignedEntityTypeLock::new()); for signed_entity_type in SignedEntityTypeDiscriminants::all().into_iter().skip(1) { locker.lock(signed_entity_type).await; } - let certifier_service = SignerCertifierService::new( - Arc::new(ticker_service), - Arc::new(DumbSignedBeaconStore::default()), - Arc::new(DumbSignedEntityConfigProvider::new( + let certifier_service = SignerCertifierService { + signed_entity_type_lock: locker.clone(), + signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), )), - Arc::new(SignedEntityTypeLock::new()), - ); + ..SignerCertifierService::dumb_dependencies(TimePoint::new(3, 14, ChainPoint::dummy())) + }; let beacon_to_sign = certifier_service.get_beacon_to_sign().await.unwrap(); let signed_discriminant: Option = @@ -175,15 +172,14 @@ mod tests { #[tokio::test] async fn mark_beacon_as_signed_update_the_store() { let signed_beacons_store = Arc::new(DumbSignedBeaconStore::default()); - let certifier_service = SignerCertifierService::new( - Arc::new(DumbTickerService::new(TimePoint::dummy())), - signed_beacons_store.clone(), - Arc::new(DumbSignedEntityConfigProvider::new( + let certifier_service = SignerCertifierService { + signed_beacon_store: signed_beacons_store.clone(), + signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), )), - Arc::new(SignedEntityTypeLock::new()), - ); + ..SignerCertifierService::dumb_dependencies(TimePoint::dummy()) + }; certifier_service .mark_beacon_as_signed(&BeaconToSign { @@ -203,16 +199,14 @@ mod tests { #[tokio::test] async fn if_already_signed_a_beacon_is_not_returned_anymore() { - let ticker_service = DumbTickerService::new(TimePoint::new(1, 14, ChainPoint::dummy())); - let certifier_service = SignerCertifierService::new( - Arc::new(ticker_service), - Arc::new(DumbSignedBeaconStore::default()), - Arc::new(DumbSignedEntityConfigProvider::new( + let certifier_service = SignerCertifierService { + signed_beacon_store: Arc::new(DumbSignedBeaconStore::default()), + signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), )), - Arc::new(SignedEntityTypeLock::new()), - ); + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; let first_beacon_to_sign = certifier_service .get_beacon_to_sign() @@ -237,16 +231,13 @@ mod tests { #[tokio::test] async fn draining_out_all_beacons_to_sign_use_signed_entity_discriminant_order() { - let ticker_service = DumbTickerService::new(TimePoint::new(1, 14, ChainPoint::dummy())); - let certifier_service = SignerCertifierService::new( - Arc::new(ticker_service), - Arc::new(DumbSignedBeaconStore::default()), - Arc::new(DumbSignedEntityConfigProvider::new( + let certifier_service = SignerCertifierService { + signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), )), - Arc::new(SignedEntityTypeLock::new()), - ); + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; let mut previous_beacon_to_sign = certifier_service .get_beacon_to_sign() @@ -278,16 +269,13 @@ mod tests { #[tokio::test] async fn draining_out_all_beacons_to_sign_doesnt_repeat_value() { - let ticker_service = DumbTickerService::new(TimePoint::new(1, 14, ChainPoint::dummy())); - let certifier_service = SignerCertifierService::new( - Arc::new(ticker_service), - Arc::new(DumbSignedBeaconStore::default()), - Arc::new(DumbSignedEntityConfigProvider::new( + let certifier_service = SignerCertifierService { + signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), )), - Arc::new(SignedEntityTypeLock::new()), - ); + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; let mut all_signed_beacons = vec![]; while let Some(beacon_to_sign) = certifier_service.get_beacon_to_sign().await.unwrap() { @@ -318,6 +306,20 @@ mod tests { use super::*; + impl SignerCertifierService { + pub fn dumb_dependencies(initial_time_point: TimePoint) -> Self { + Self { + ticker_service: Arc::new(DumbTickerService::new(initial_time_point)), + signed_beacon_store: Arc::new(DumbSignedBeaconStore::default()), + signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( + CardanoTransactionsSigningConfig::dummy(), + SignedEntityTypeDiscriminants::all(), + )), + signed_entity_type_lock: Arc::new(SignedEntityTypeLock::new()), + } + } + } + pub struct DumbTickerService { time_point: TimePoint, } From ab2906d3c240780b6ed90a371530b77668b296a2 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:25:38 +0200 Subject: [PATCH 09/13] refactor: move responsibility of computing/publishing signatures to certifier in signer --- .../src/dependency_injection/builder.rs | 2 + mithril-signer/src/runtime/runner.rs | 175 ++---------------- mithril-signer/src/runtime/state_machine.rs | 19 +- .../src/services/aggregator_client.rs | 17 +- mithril-signer/src/services/certifier.rs | 147 ++++++++++++++- .../test_extensions/state_machine_tester.rs | 2 + 6 files changed, 187 insertions(+), 175 deletions(-) diff --git a/mithril-signer/src/dependency_injection/builder.rs b/mithril-signer/src/dependency_injection/builder.rs index 8c533a67460..1616bbabb14 100644 --- a/mithril-signer/src/dependency_injection/builder.rs +++ b/mithril-signer/src/dependency_injection/builder.rs @@ -371,6 +371,8 @@ impl<'a> DependenciesBuilder<'a> { epoch_service.clone(), )), signed_entity_type_lock.clone(), + single_signer.clone(), + aggregator_client.clone(), )); let services = SignerDependencyContainer { diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 80f18fe441f..8852e8ab78e 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -1,12 +1,12 @@ use anyhow::Context; use async_trait::async_trait; -use slog_scope::{debug, info, warn}; +use slog_scope::{debug, warn}; use thiserror::Error; use tokio::sync::RwLockReadGuard; use mithril_common::crypto_helper::{KESPeriod, OpCert, ProtocolOpCert, SerDeShelleyFileFormat}; use mithril_common::entities::{ - Epoch, PartyId, ProtocolMessage, SignedEntityType, Signer, SingleSignatures, TimePoint, + Epoch, PartyId, ProtocolMessage, SignedEntityType, Signer, TimePoint, }; use mithril_common::StdResult; use mithril_persistence::store::StakeStorer; @@ -47,17 +47,10 @@ pub trait Runner: Send + Sync { ) -> StdResult; /// Create the single signature. - async fn compute_single_signature( + async fn compute_publish_single_signature( &self, + beacon_to_sign: &BeaconToSign, message: &ProtocolMessage, - ) -> StdResult>; - - /// Send the single signature to the aggregator in order to be aggregated. - async fn send_single_signature( - &self, - signed_entity_type: &SignedEntityType, - maybe_signature: Option, - signed_message: &ProtocolMessage, ) -> StdResult<()>; /// Mark the beacon as signed. @@ -277,51 +270,16 @@ impl Runner for SignerRunner { Ok(protocol_message) } - async fn compute_single_signature( + async fn compute_publish_single_signature( &self, + beacon_to_sign: &BeaconToSign, message: &ProtocolMessage, - ) -> StdResult> { - debug!("RUNNER: compute_single_signature"); - - let signature = self - .services - .single_signer - .compute_single_signatures(message) - .await?; - info!( - " > {}", - if signature.is_some() { - "could compute a single signature!" - } else { - "NO single signature was computed." - } - ); - - Ok(signature) - } - - async fn send_single_signature( - &self, - signed_entity_type: &SignedEntityType, - maybe_signature: Option, - protocol_message: &ProtocolMessage, ) -> StdResult<()> { - debug!("RUNNER: send_single_signature"); - - if let Some(single_signatures) = maybe_signature { - debug!(" > there is a single signature to send"); - - self.services - .certificate_handler - .register_signatures(signed_entity_type, &single_signatures, protocol_message) - .await?; - - Ok(()) - } else { - debug!(" > NO single signature to send, doing nothing"); - - Ok(()) - } + debug!("RUNNER: compute_publish_single_signature"); + self.services + .certifier + .compute_publish_single_signature(beacon_to_sign, message) + .await } async fn mark_beacon_as_signed(&self, beacon: &BeaconToSign) -> StdResult<()> { @@ -383,9 +341,7 @@ mod tests { MKMap, MKMapNode, MKTreeNode, MKTreeStoreInMemory, MKTreeStorer, ProtocolInitializer, }, digesters::{DumbImmutableDigester, DumbImmutableFileObserver}, - entities::{ - BlockNumber, BlockRange, Epoch, ProtocolMessagePartKey, SignedEntityTypeDiscriminants, - }, + entities::{BlockNumber, BlockRange, Epoch, SignedEntityTypeDiscriminants}, era::{adapters::EraReaderBootstrapAdapter, EraChecker, EraReader}, messages::{AggregatorCapabilities, AggregatorFeaturesMessage}, signable_builder::{ @@ -405,9 +361,8 @@ mod tests { use crate::metrics::MetricsService; use crate::services::{ CardanoTransactionsImporter, DumbAggregatorClient, MithrilEpochService, - MithrilSingleSigner, MockAggregatorClient, MockTransactionStore, MockUpkeepService, - SignerCertifierService, SignerSignableSeedBuilder, SignerSignedEntityConfigProvider, - SingleSigner, + MithrilSingleSigner, MockTransactionStore, MockUpkeepService, SignerCertifierService, + SignerSignableSeedBuilder, SignerSignedEntityConfigProvider, }; use crate::store::ProtocolInitializerStore; @@ -523,6 +478,7 @@ mod tests { Arc::new(CardanoTransactionsPreloaderActivation::new(true)), )); let upkeep_service = Arc::new(MockUpkeepService::new()); + let aggregator_client = Arc::new(DumbAggregatorClient::default()); let certifier = Arc::new(SignerCertifierService::new( ticker_service.clone(), Arc::new(SignedBeaconRepository::new(sqlite_connection.clone(), None)), @@ -531,11 +487,13 @@ mod tests { epoch_service.clone(), )), signed_entity_type_lock.clone(), + single_signer.clone(), + aggregator_client.clone(), )); SignerDependencyContainer { stake_store, - certificate_handler: Arc::new(DumbAggregatorClient::default()), + certificate_handler: aggregator_client, chain_observer, digester, single_signer, @@ -666,103 +624,6 @@ mod tests { ); } - #[tokio::test] - async fn test_compute_single_signature() { - let mut services = init_services().await; - let current_time_point = services - .ticker_service - .get_current_time_point() - .await - .expect("get_current_time_point should not fail"); - let fixture = MithrilFixtureBuilder::default().with_signers(5).build(); - let signer_with_stake = fixture.signers_fixture()[0].signer_with_stake.clone(); - let protocol_initializer = fixture.signers_fixture()[0].protocol_initializer.clone(); - - let single_signer = Arc::new(MithrilSingleSigner::new( - signer_with_stake.party_id.to_string(), - services.epoch_service.clone(), - )); - services.single_signer = single_signer.clone(); - services - .protocol_initializer_store - .save_protocol_initializer( - current_time_point - .epoch - .offset_to_signer_retrieval_epoch() - .expect("offset_to_signer_retrieval_epoch should not fail"), - protocol_initializer.clone(), - ) - .await - .expect("save_protocol_initializer should not fail"); - - services - .stake_store - .save_stakes( - current_time_point - .epoch - .offset_to_signer_retrieval_epoch() - .expect("offset_to_signer_retrieval_epoch should not fail"), - fixture.stake_distribution(), - ) - .await - .expect("save_stakes should not fail"); - - let signers = &fixture.signers()[0..3]; - - let mut message = ProtocolMessage::new(); - message.set_message_part( - ProtocolMessagePartKey::SnapshotDigest, - "a message".to_string(), - ); - message.set_message_part( - ProtocolMessagePartKey::NextAggregateVerificationKey, - "an avk".to_string(), - ); - - let runner = init_runner(Some(services), None).await; - - // inform epoch settings - let epoch_settings = SignerEpochSettings { - epoch: current_time_point.epoch, - current_signers: signers.to_vec(), - next_signers: fixture.signers(), - ..SignerEpochSettings::dummy().clone() - }; - runner.inform_epoch_settings(epoch_settings).await.unwrap(); - - let expected = single_signer - .compute_single_signatures(&message) - .await - .expect("compute_single_signatures should not fail"); - - let single_signature = runner - .compute_single_signature(&message) - .await - .expect("compute_message should not fail"); - assert_eq!(expected, single_signature); - } - - #[tokio::test] - async fn test_send_single_signature() { - let mut services = init_services().await; - let mut certificate_handler = MockAggregatorClient::new(); - certificate_handler - .expect_register_signatures() - .once() - .returning(|_, _, _| Ok(())); - services.certificate_handler = Arc::new(certificate_handler); - let runner = init_runner(Some(services), None).await; - - runner - .send_single_signature( - &SignedEntityType::dummy(), - Some(fake_data::single_signatures(vec![2, 5, 12])), - &ProtocolMessage::default(), - ) - .await - .expect("send_single_signature should not fail"); - } - #[tokio::test] async fn test_update_era_checker() { let services = init_services().await; diff --git a/mithril-signer/src/runtime/state_machine.rs b/mithril-signer/src/runtime/state_machine.rs index 6d995c3889d..2b7cb6c0c7e 100644 --- a/mithril-signer/src/runtime/state_machine.rs +++ b/mithril-signer/src/runtime/state_machine.rs @@ -375,17 +375,10 @@ impl StateMachine { nested_error: Some(e) })?; - let single_signatures = self - .runner - .compute_single_signature(&message) + self.runner.compute_publish_single_signature(&beacon_to_sign, &message) .await .map_err(|e| RuntimeError::KeepState { - message: format!("Could not compute single signature during 'ready to sign → ready to sign' phase (current epoch {current_epoch:?})"), - nested_error: Some(e) - })?; - self.runner.send_single_signature(&beacon_to_sign.signed_entity_type, single_signatures, &message).await - .map_err(|e| RuntimeError::KeepState { - message: format!("Could not send single signature during 'ready to sign → ready to sign' phase (current epoch {current_epoch:?})"), + message: format!("Could not compute and publish single signature during 'ready to sign → ready to sign' phase (current epoch {current_epoch:?})"), nested_error: Some(e) })?; self.runner.mark_beacon_as_signed(&beacon_to_sign).await @@ -722,18 +715,14 @@ mod tests { .expect_get_beacon_to_sign() .once() .returning(move || Ok(Some(beacon_to_sign_clone.clone()))); - runner - .expect_compute_single_signature() - .once() - .returning(|_| Ok(Some(fake_data::single_signatures(vec![1, 5, 23])))); runner .expect_compute_message() .once() .returning(|_| Ok(ProtocolMessage::new())); runner - .expect_send_single_signature() + .expect_compute_publish_single_signature() .once() - .returning(|_, _, _| Ok(())); + .returning(|_, _| Ok(())); runner .expect_mark_beacon_as_signed() .once() diff --git a/mithril-signer/src/services/aggregator_client.rs b/mithril-signer/src/services/aggregator_client.rs index e0d2fda1ba8..410b707d5be 100644 --- a/mithril-signer/src/services/aggregator_client.rs +++ b/mithril-signer/src/services/aggregator_client.rs @@ -11,13 +11,14 @@ use mithril_common::{ messages::{ AggregatorFeaturesMessage, EpochSettingsMessage, TryFromMessageAdapter, TryToMessageAdapter, }, - StdError, MITHRIL_API_VERSION_HEADER, MITHRIL_SIGNER_VERSION_HEADER, + StdError, StdResult, MITHRIL_API_VERSION_HEADER, MITHRIL_SIGNER_VERSION_HEADER, }; use crate::entities::SignerEpochSettings; use crate::message_adapters::{ FromEpochSettingsAdapter, ToRegisterSignatureMessageAdapter, ToRegisterSignerMessageAdapter, }; +use crate::services::SignaturePublisher; /// Error structure for the Aggregator Client. #[derive(Error, Debug)] @@ -97,6 +98,20 @@ pub trait AggregatorClient: Sync + Send { ) -> Result; } +#[async_trait] +impl SignaturePublisher for T { + async fn publish( + &self, + signed_entity_type: &SignedEntityType, + signatures: &SingleSignatures, + protocol_message: &ProtocolMessage, + ) -> StdResult<()> { + self.register_signatures(signed_entity_type, signatures, protocol_message) + .await?; + Ok(()) + } +} + /// AggregatorHTTPClient is a http client for an aggregator pub struct AggregatorHTTPClient { aggregator_endpoint: String, diff --git a/mithril-signer/src/services/certifier.rs b/mithril-signer/src/services/certifier.rs index 06b2e7977ec..44d680f527c 100644 --- a/mithril-signer/src/services/certifier.rs +++ b/mithril-signer/src/services/certifier.rs @@ -1,12 +1,16 @@ use async_trait::async_trait; use chrono::Utc; +use slog_scope::debug; use std::sync::Arc; -use mithril_common::entities::{SignedEntityConfig, SignedEntityType, TimePoint}; +use mithril_common::entities::{ + ProtocolMessage, SignedEntityConfig, SignedEntityType, SingleSignatures, TimePoint, +}; use mithril_common::signed_entity_type_lock::SignedEntityTypeLock; use mithril_common::{StdResult, TickerService}; use crate::entities::BeaconToSign; +use crate::services::SingleSigner; /// Certifier Service /// @@ -21,6 +25,13 @@ pub trait CertifierService: Sync + Send { /// Mark a beacon as signed so it won't be returned by `get_beacon_to_sign` anymore. async fn mark_beacon_as_signed(&self, signed_beacon: &BeaconToSign) -> StdResult<()>; + + /// Compute and publish a single signature for a given protocol message. + async fn compute_publish_single_signature( + &self, + beacon_to_sign: &BeaconToSign, + protocol_message: &ProtocolMessage, + ) -> StdResult<()>; } /// Trait to provide the current signed entity configuration that can change over time. @@ -45,12 +56,27 @@ pub trait SignedBeaconStore: Sync + Send { async fn mark_beacon_as_signed(&self, entity: &BeaconToSign) -> StdResult<()>; } +/// Publishes computed single signatures to a third party. +#[cfg_attr(test, mockall::automock)] +#[async_trait] +pub trait SignaturePublisher: Send + Sync { + /// Publish computed single signatures. + async fn publish( + &self, + signed_entity_type: &SignedEntityType, + signatures: &SingleSignatures, + protocol_message: &ProtocolMessage, + ) -> StdResult<()>; +} + /// Implementation of the [Certifier Service][CertifierService] for the Mithril Signer. pub struct SignerCertifierService { ticker_service: Arc, signed_beacon_store: Arc, signed_entity_config_provider: Arc, signed_entity_type_lock: Arc, + single_signer: Arc, + signature_publisher: Arc, } impl SignerCertifierService { @@ -60,12 +86,16 @@ impl SignerCertifierService { signed_beacon_store: Arc, signed_entity_config_provider: Arc, signed_entity_type_lock: Arc, + single_signer: Arc, + signature_publisher: Arc, ) -> Self { Self { ticker_service, signed_beacon_store, signed_entity_config_provider, signed_entity_type_lock, + single_signer, + signature_publisher, } } @@ -115,13 +145,44 @@ impl CertifierService for SignerCertifierService { .mark_beacon_as_signed(signed_beacon) .await } + + async fn compute_publish_single_signature( + &self, + beacon_to_sign: &BeaconToSign, + protocol_message: &ProtocolMessage, + ) -> StdResult<()> { + if let Some(single_signatures) = self + .single_signer + .compute_single_signatures(protocol_message) + .await? + { + debug!(" > there is a single signature to send"); + self.signature_publisher + .publish( + &beacon_to_sign.signed_entity_type, + &single_signatures, + protocol_message, + ) + .await?; + } else { + debug!(" > NO single signature to send, doing nothing"); + } + + Ok(()) + } } #[cfg(test)] mod tests { + use mockall::predicate::eq; + use mithril_common::entities::{ - CardanoTransactionsSigningConfig, ChainPoint, Epoch, SignedEntityTypeDiscriminants, + CardanoTransactionsSigningConfig, ChainPoint, Epoch, ProtocolMessagePartKey, + SignedEntityTypeDiscriminants, }; + use mithril_common::test_utils::fake_data; + + use crate::services::MockSingleSigner; use super::{tests::tests_tooling::*, *}; @@ -298,6 +359,86 @@ mod tests { ); } + #[tokio::test] + async fn compute_publish_single_signature_success_if_a_signature_was_issued() { + let protocol_message = { + let mut message = ProtocolMessage::new(); + message.set_message_part(ProtocolMessagePartKey::SnapshotDigest, "digest".to_string()); + message + }; + let beacon_to_sign = BeaconToSign::new( + Epoch(1), + SignedEntityType::MithrilStakeDistribution(Epoch(4)), + Utc::now(), + ); + + let certifier_service = SignerCertifierService { + single_signer: { + let mut single_signer = MockSingleSigner::new(); + single_signer + .expect_compute_single_signatures() + .with(eq(protocol_message.clone())) + .return_once(|_| Ok(Some(fake_data::single_signatures(vec![1, 5, 12])))); + Arc::new(single_signer) + }, + signature_publisher: { + let mut signature_publisher = MockSignaturePublisher::new(); + signature_publisher + .expect_publish() + .with( + eq(beacon_to_sign.signed_entity_type.clone()), + eq(fake_data::single_signatures(vec![1, 5, 12])), + eq(protocol_message.clone()), + ) + .returning(|_, _, _| Ok(())); + Arc::new(signature_publisher) + }, + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; + + certifier_service + .compute_publish_single_signature(&beacon_to_sign, &protocol_message) + .await + .expect("Single signature should be computed and published"); + } + + #[tokio::test] + async fn compute_publish_single_signature_success_but_dont_publish_if_no_signature_were_issued() + { + let protocol_message = { + let mut message = ProtocolMessage::new(); + message.set_message_part(ProtocolMessagePartKey::SnapshotDigest, "digest".to_string()); + message + }; + let beacon_to_sign = BeaconToSign::new( + Epoch(1), + SignedEntityType::MithrilStakeDistribution(Epoch(4)), + Utc::now(), + ); + + let certifier_service = SignerCertifierService { + single_signer: { + let mut single_signer = MockSingleSigner::new(); + single_signer + .expect_compute_single_signatures() + .with(eq(protocol_message.clone())) + .return_once(|_| Ok(None)); + Arc::new(single_signer) + }, + signature_publisher: { + let mut signature_publisher = MockSignaturePublisher::new(); + signature_publisher.expect_publish().never(); + Arc::new(signature_publisher) + }, + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; + + certifier_service + .compute_publish_single_signature(&beacon_to_sign, &protocol_message) + .await + .unwrap(); + } + pub mod tests_tooling { use std::collections::BTreeSet; use tokio::sync::RwLock; @@ -316,6 +457,8 @@ mod tests { SignedEntityTypeDiscriminants::all(), )), signed_entity_type_lock: Arc::new(SignedEntityTypeLock::new()), + single_signer: Arc::new(MockSingleSigner::new()), + signature_publisher: Arc::new(MockSignaturePublisher::new()), } } } diff --git a/mithril-signer/tests/test_extensions/state_machine_tester.rs b/mithril-signer/tests/test_extensions/state_machine_tester.rs index 6249f2ff25a..c4987ea8e69 100644 --- a/mithril-signer/tests/test_extensions/state_machine_tester.rs +++ b/mithril-signer/tests/test_extensions/state_machine_tester.rs @@ -262,6 +262,8 @@ impl StateMachineTester { epoch_service.clone(), )), signed_entity_type_lock.clone(), + single_signer.clone(), + certificate_handler.clone(), )); let services = SignerDependencyContainer { From 3681e2b996c904e4e95ccd74f3ef0700f7ea7007 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:42:38 +0200 Subject: [PATCH 10/13] refactor: simplify signer certifier api By removing `mark_beacon_as_signed` from its public api since the "compute/publish" signatures can now execute it directly. --- mithril-signer/src/runtime/runner.rs | 9 -- mithril-signer/src/runtime/state_machine.rs | 10 -- mithril-signer/src/services/certifier.rs | 140 ++++++++++++++------ 3 files changed, 98 insertions(+), 61 deletions(-) diff --git a/mithril-signer/src/runtime/runner.rs b/mithril-signer/src/runtime/runner.rs index 8852e8ab78e..d5b74701ee2 100644 --- a/mithril-signer/src/runtime/runner.rs +++ b/mithril-signer/src/runtime/runner.rs @@ -53,9 +53,6 @@ pub trait Runner: Send + Sync { message: &ProtocolMessage, ) -> StdResult<()>; - /// Mark the beacon as signed. - async fn mark_beacon_as_signed(&self, beacon: &BeaconToSign) -> StdResult<()>; - /// Read the current era and update the EraChecker. async fn update_era_checker(&self, epoch: Epoch) -> StdResult<()>; @@ -282,12 +279,6 @@ impl Runner for SignerRunner { .await } - async fn mark_beacon_as_signed(&self, beacon: &BeaconToSign) -> StdResult<()> { - debug!("RUNNER: mark_beacon_as_signed"; "beacon" => ?beacon); - - self.services.certifier.mark_beacon_as_signed(beacon).await - } - async fn update_era_checker(&self, epoch: Epoch) -> StdResult<()> { debug!("RUNNER: update_era_checker"); diff --git a/mithril-signer/src/runtime/state_machine.rs b/mithril-signer/src/runtime/state_machine.rs index 2b7cb6c0c7e..97db5699da2 100644 --- a/mithril-signer/src/runtime/state_machine.rs +++ b/mithril-signer/src/runtime/state_machine.rs @@ -381,11 +381,6 @@ impl StateMachine { message: format!("Could not compute and publish single signature during 'ready to sign → ready to sign' phase (current epoch {current_epoch:?})"), nested_error: Some(e) })?; - self.runner.mark_beacon_as_signed(&beacon_to_sign).await - .map_err(|e| RuntimeError::KeepState { - message: format!("Could not mark beacon as signed during 'ready to sign → ready to sign' phase (current epoch {current_epoch:?})"), - nested_error: Some(e) - })?; self.metrics_service .signature_registration_success_since_startup_counter_increment(); @@ -723,11 +718,6 @@ mod tests { .expect_compute_publish_single_signature() .once() .returning(|_, _| Ok(())); - runner - .expect_mark_beacon_as_signed() - .once() - .with(predicate::eq(beacon_to_sign)) - .returning(|_| Ok(())); let state_machine = init_state_machine( SignerState::ReadyToSign { diff --git a/mithril-signer/src/services/certifier.rs b/mithril-signer/src/services/certifier.rs index 44d680f527c..bc28971816a 100644 --- a/mithril-signer/src/services/certifier.rs +++ b/mithril-signer/src/services/certifier.rs @@ -23,9 +23,6 @@ pub trait CertifierService: Sync + Send { /// If all available signed entity have already been signed, `None` is returned. async fn get_beacon_to_sign(&self) -> StdResult>; - /// Mark a beacon as signed so it won't be returned by `get_beacon_to_sign` anymore. - async fn mark_beacon_as_signed(&self, signed_beacon: &BeaconToSign) -> StdResult<()>; - /// Compute and publish a single signature for a given protocol message. async fn compute_publish_single_signature( &self, @@ -140,12 +137,6 @@ impl CertifierService for SignerCertifierService { } } - async fn mark_beacon_as_signed(&self, signed_beacon: &BeaconToSign) -> StdResult<()> { - self.signed_beacon_store - .mark_beacon_as_signed(signed_beacon) - .await - } - async fn compute_publish_single_signature( &self, beacon_to_sign: &BeaconToSign, @@ -165,9 +156,14 @@ impl CertifierService for SignerCertifierService { ) .await?; } else { - debug!(" > NO single signature to send, doing nothing"); + debug!(" > NO single signature to send"); } + debug!(" > marking beacon as signed"; "beacon" => ?beacon_to_sign); + self.signed_beacon_store + .mark_beacon_as_signed(beacon_to_sign) + .await?; + Ok(()) } } @@ -230,38 +226,11 @@ mod tests { ); } - #[tokio::test] - async fn mark_beacon_as_signed_update_the_store() { - let signed_beacons_store = Arc::new(DumbSignedBeaconStore::default()); - let certifier_service = SignerCertifierService { - signed_beacon_store: signed_beacons_store.clone(), - signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( - CardanoTransactionsSigningConfig::dummy(), - SignedEntityTypeDiscriminants::all(), - )), - ..SignerCertifierService::dumb_dependencies(TimePoint::dummy()) - }; - - certifier_service - .mark_beacon_as_signed(&BeaconToSign { - epoch: Epoch(1), - signed_entity_type: SignedEntityType::MithrilStakeDistribution(Epoch(4)), - initiated_at: Utc::now(), - }) - .await - .unwrap(); - - let signed_beacons = signed_beacons_store.signed_beacons().await; - assert_eq!( - vec![SignedEntityType::MithrilStakeDistribution(Epoch(4))], - signed_beacons - ); - } - #[tokio::test] async fn if_already_signed_a_beacon_is_not_returned_anymore() { + let signed_beacon_store = Arc::new(DumbSignedBeaconStore::default()); let certifier_service = SignerCertifierService { - signed_beacon_store: Arc::new(DumbSignedBeaconStore::default()), + signed_beacon_store: signed_beacon_store.clone(), signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), @@ -274,7 +243,7 @@ mod tests { .await .unwrap() .unwrap(); - certifier_service + signed_beacon_store .mark_beacon_as_signed(&first_beacon_to_sign.clone()) .await .unwrap(); @@ -292,7 +261,9 @@ mod tests { #[tokio::test] async fn draining_out_all_beacons_to_sign_use_signed_entity_discriminant_order() { + let signed_beacon_store = Arc::new(DumbSignedBeaconStore::default()); let certifier_service = SignerCertifierService { + signed_beacon_store: signed_beacon_store.clone(), signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), @@ -307,7 +278,7 @@ mod tests { .expect("There should be a beacon to sign since nothing is locked or signed"); loop { - certifier_service + signed_beacon_store .mark_beacon_as_signed(&previous_beacon_to_sign) .await .unwrap(); @@ -330,7 +301,9 @@ mod tests { #[tokio::test] async fn draining_out_all_beacons_to_sign_doesnt_repeat_value() { + let signed_beacon_store = Arc::new(DumbSignedBeaconStore::default()); let certifier_service = SignerCertifierService { + signed_beacon_store: signed_beacon_store.clone(), signed_entity_config_provider: Arc::new(DumbSignedEntityConfigProvider::new( CardanoTransactionsSigningConfig::dummy(), SignedEntityTypeDiscriminants::all(), @@ -340,7 +313,7 @@ mod tests { let mut all_signed_beacons = vec![]; while let Some(beacon_to_sign) = certifier_service.get_beacon_to_sign().await.unwrap() { - certifier_service + signed_beacon_store .mark_beacon_as_signed(&beacon_to_sign) .await .unwrap(); @@ -372,6 +345,7 @@ mod tests { Utc::now(), ); + let signed_beacons_store = Arc::new(DumbSignedBeaconStore::default()); let certifier_service = SignerCertifierService { single_signer: { let mut single_signer = MockSingleSigner::new(); @@ -393,6 +367,7 @@ mod tests { .returning(|_, _, _| Ok(())); Arc::new(signature_publisher) }, + signed_beacon_store: signed_beacons_store.clone(), ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) }; @@ -400,6 +375,12 @@ mod tests { .compute_publish_single_signature(&beacon_to_sign, &protocol_message) .await .expect("Single signature should be computed and published"); + + let signed_beacons = signed_beacons_store.signed_beacons().await; + assert_eq!( + vec![beacon_to_sign.signed_entity_type.clone()], + signed_beacons + ); } #[tokio::test] @@ -416,6 +397,7 @@ mod tests { Utc::now(), ); + let signed_beacons_store = Arc::new(DumbSignedBeaconStore::default()); let certifier_service = SignerCertifierService { single_signer: { let mut single_signer = MockSingleSigner::new(); @@ -430,6 +412,7 @@ mod tests { signature_publisher.expect_publish().never(); Arc::new(signature_publisher) }, + signed_beacon_store: signed_beacons_store.clone(), ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) }; @@ -437,6 +420,79 @@ mod tests { .compute_publish_single_signature(&beacon_to_sign, &protocol_message) .await .unwrap(); + + let signed_beacons = signed_beacons_store.signed_beacons().await; + assert_eq!( + vec![beacon_to_sign.signed_entity_type.clone()], + signed_beacons + ); + } + + #[tokio::test] + async fn beacon_isnt_mark_as_signed_if_computing_signature_fails() { + let beacon_to_sign = BeaconToSign::new( + Epoch(1), + SignedEntityType::MithrilStakeDistribution(Epoch(4)), + Utc::now(), + ); + + let signed_beacons_store = Arc::new(DumbSignedBeaconStore::default()); + let certifier_service = SignerCertifierService { + single_signer: { + let mut single_signer = MockSingleSigner::new(); + single_signer + .expect_compute_single_signatures() + .return_once(|_| Err(anyhow::anyhow!("error"))); + Arc::new(single_signer) + }, + signed_beacon_store: signed_beacons_store.clone(), + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; + + certifier_service + .compute_publish_single_signature(&beacon_to_sign, &ProtocolMessage::new()) + .await + .unwrap_err(); + + let signed_beacons = signed_beacons_store.signed_beacons().await; + assert_eq!(Vec::::new(), signed_beacons); + } + + #[tokio::test] + async fn beacon_isnt_mark_as_signed_if_publishing_signature_fails() { + let beacon_to_sign = BeaconToSign::new( + Epoch(1), + SignedEntityType::MithrilStakeDistribution(Epoch(4)), + Utc::now(), + ); + + let signed_beacons_store = Arc::new(DumbSignedBeaconStore::default()); + let certifier_service = SignerCertifierService { + single_signer: { + let mut single_signer = MockSingleSigner::new(); + single_signer + .expect_compute_single_signatures() + .return_once(|_| Ok(Some(fake_data::single_signatures(vec![1, 5, 12])))); + Arc::new(single_signer) + }, + signature_publisher: { + let mut signature_publisher = MockSignaturePublisher::new(); + signature_publisher + .expect_publish() + .return_once(|_, _, _| Err(anyhow::anyhow!("error"))); + Arc::new(signature_publisher) + }, + signed_beacon_store: signed_beacons_store.clone(), + ..SignerCertifierService::dumb_dependencies(TimePoint::new(1, 14, ChainPoint::dummy())) + }; + + certifier_service + .compute_publish_single_signature(&beacon_to_sign, &ProtocolMessage::new()) + .await + .unwrap_err(); + + let signed_beacons = signed_beacons_store.signed_beacons().await; + assert_eq!(Vec::::new(), signed_beacons); } pub mod tests_tooling { From 7b59db8925f38f2e2aca3bfe2eb668d0757bc5a2 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:01:11 +0200 Subject: [PATCH 11/13] test: adjustements following PR reviews --- mithril-signer/src/services/epoch_service.rs | 164 +++++++++---------- 1 file changed, 74 insertions(+), 90 deletions(-) diff --git a/mithril-signer/src/services/epoch_service.rs b/mithril-signer/src/services/epoch_service.rs index 1c9bc69e669..f52227340c2 100644 --- a/mithril-signer/src/services/epoch_service.rs +++ b/mithril-signer/src/services/epoch_service.rs @@ -514,99 +514,83 @@ mod tests { .unwrap()); } - #[test] - fn signer_cant_sign_if_no_protocol_initializer_are_stored() { - let epoch = Epoch(12); - let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); - let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); - let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( - Box::new(DumbStoreAdapter::new()), - None, - )); - - let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) - .set_data_to_default_or_fake(epoch) - .alter_data(|data| { - data.protocol_initializer = None; - data.current_signers = fixtures.signers(); - }); - - let can_sign_current_epoch = epoch_service - .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) - .unwrap(); - assert!(!can_sign_current_epoch); - } - - #[test] - fn signer_cant_sign_if_it_dont_use_stored_protocol_initializer() { - let epoch = Epoch(12); - let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); - let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); - let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( - Box::new(DumbStoreAdapter::new()), - None, - )); - - let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) - .set_data_to_default_or_fake(epoch) - .alter_data(|data| { - data.protocol_initializer = - Some(fixtures.signers_fixture()[2].protocol_initializer.clone()); - data.current_signers = fixtures.signers(); - }); - - let can_sign_current_epoch = epoch_service - .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) - .unwrap(); - assert!(!can_sign_current_epoch); - } - - #[test] - fn signer_cant_sign_if_not_in_current_signers() { - let epoch = Epoch(12); - let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); - let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); - let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( - Box::new(DumbStoreAdapter::new()), - None, - )); - - let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) - .set_data_to_default_or_fake(epoch) - .alter_data(|data| { - data.protocol_initializer = - Some(fixtures.signers_fixture()[0].protocol_initializer.clone()); - data.current_signers = fixtures.signers()[2..].to_vec(); - }); - - let can_sign_current_epoch = epoch_service - .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) - .unwrap(); - assert!(!can_sign_current_epoch); - } + mod can_signer_sign_current_epoch { + use super::*; + + #[test] + fn cant_sign_if_no_protocol_initializer_are_stored() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + + let epoch_service = MithrilEpochService::new_with_dumb_dependencies() + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = None; + data.current_signers = fixtures.signers(); + }); + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(!can_sign_current_epoch); + } - #[test] - fn signer_can_sign_if_in_current_signers_and_use_the_stored_protocol_initializer() { - let epoch = Epoch(12); - let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); - let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None)); - let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new( - Box::new(DumbStoreAdapter::new()), - None, - )); + #[test] + fn cant_sign_if_stored_protocol_initializer_belong_to_another_party() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + + let epoch_service = MithrilEpochService::new_with_dumb_dependencies() + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = + Some(fixtures.signers_fixture()[2].protocol_initializer.clone()); + data.current_signers = fixtures.signers(); + }); + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(!can_sign_current_epoch); + } - let epoch_service = MithrilEpochService::new(stake_store, protocol_initializer_store) - .set_data_to_default_or_fake(epoch) - .alter_data(|data| { - data.protocol_initializer = - Some(fixtures.signers_fixture()[0].protocol_initializer.clone()); - data.current_signers = fixtures.signers(); - }); + #[test] + fn cant_sign_if_not_in_current_signers() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + + let epoch_service = MithrilEpochService::new_with_dumb_dependencies() + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = + Some(fixtures.signers_fixture()[0].protocol_initializer.clone()); + data.current_signers = fixtures.signers()[2..].to_vec(); + }); + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(!can_sign_current_epoch); + } - let can_sign_current_epoch = epoch_service - .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) - .unwrap(); - assert!(can_sign_current_epoch); + #[test] + fn can_sign_if_in_current_signers_and_use_the_stored_protocol_initializer() { + let epoch = Epoch(12); + let fixtures = MithrilFixtureBuilder::default().with_signers(10).build(); + + let epoch_service = MithrilEpochService::new_with_dumb_dependencies() + .set_data_to_default_or_fake(epoch) + .alter_data(|data| { + data.protocol_initializer = + Some(fixtures.signers_fixture()[0].protocol_initializer.clone()); + data.current_signers = fixtures.signers(); + }); + + let can_sign_current_epoch = epoch_service + .can_signer_sign_current_epoch(fixtures.signers()[0].party_id.clone()) + .unwrap(); + assert!(can_sign_current_epoch); + } } #[tokio::test] From ba1f77fcd1142776fc2e330bc5dce55b829e8982 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:03:27 +0200 Subject: [PATCH 12/13] style(test): reorder `MockEpochServiceImpl` to match trait definition + remove duplicate method comments. --- mithril-signer/src/services/epoch_service.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/mithril-signer/src/services/epoch_service.rs b/mithril-signer/src/services/epoch_service.rs index f52227340c2..ae70f5235cb 100644 --- a/mithril-signer/src/services/epoch_service.rs +++ b/mithril-signer/src/services/epoch_service.rs @@ -364,43 +364,32 @@ pub mod mock_epoch_service { #[async_trait] impl EpochService for EpochServiceImpl { - /// Inform the service a new epoch has been detected, telling it to update its - /// internal state for the new epoch. async fn inform_epoch_settings( &mut self, epoch_settings: SignerEpochSettings, allowed_discriminants: BTreeSet, ) -> StdResult<()>; - /// Get the current epoch for which the data stored in this service are computed. fn epoch_of_current_data(&self) -> StdResult; - /// Get next protocol parameters used in next epoch (associated with the actual epoch) fn next_protocol_parameters(&self) -> StdResult<&'static ProtocolParameters>; fn protocol_initializer(&self) -> StdResult<&'static Option>; - /// Get signers for the current epoch fn current_signers(&self) -> StdResult<&'static Vec>; - /// Get signers for the next epoch fn next_signers(&self) -> StdResult<&'static Vec>; - /// Get the list of signed entity types that are allowed to sign for the current epoch - fn allowed_discriminants(&self) -> StdResult<&'static BTreeSet>; - - /// Get signers with stake for the current epoch async fn current_signers_with_stake(&self) -> StdResult>; - /// Get signers with stake for the next epoch async fn next_signers_with_stake(&self) -> StdResult>; - /// Get the cardano transactions signing configuration for the current epoch + fn allowed_discriminants(&self) -> StdResult<&'static BTreeSet>; + fn cardano_transactions_signing_config( &self, ) -> StdResult<&'static Option>; - /// Get the cardano transactions signing configuration for the next epoch fn next_cardano_transactions_signing_config( &self, ) -> StdResult<&'static Option>; From 8c8b8d25bdaf0f6f8d63471a3d4c8ba2e7d828f9 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:46:26 +0200 Subject: [PATCH 13/13] chore: upgrade crate versions * mithril-common from `0.4.63` to `0.4.64` * mithril-signer from `0.2.193` to `0.2.194` --- Cargo.lock | 4 ++-- mithril-common/Cargo.toml | 2 +- mithril-signer/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c77995b9f87..f6dc8b60cc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3559,7 +3559,7 @@ dependencies = [ [[package]] name = "mithril-common" -version = "0.4.63" +version = "0.4.64" dependencies = [ "anyhow", "async-trait", @@ -3703,7 +3703,7 @@ dependencies = [ [[package]] name = "mithril-signer" -version = "0.2.193" +version = "0.2.194" dependencies = [ "anyhow", "async-trait", diff --git a/mithril-common/Cargo.toml b/mithril-common/Cargo.toml index 5c41b8a1269..e9f4d168f2f 100644 --- a/mithril-common/Cargo.toml +++ b/mithril-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-common" -version = "0.4.63" +version = "0.4.64" 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 743cf96f446..33fa2627175 100644 --- a/mithril-signer/Cargo.toml +++ b/mithril-signer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-signer" -version = "0.2.193" +version = "0.2.194" description = "A Mithril Signer" authors = { workspace = true } edition = { workspace = true }