From 2570d1da883ce81aa12894d1a5583c121d2dc449 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Raynaud Date: Fri, 28 Apr 2023 16:14:10 +0200 Subject: [PATCH 1/5] Update Artifact trait --- .../src/artifact_builder/dummy_artifact.rs | 19 ++++++------------- .../src/artifact_builder/interface.rs | 10 +++++++--- .../src/signable_builder/interface.rs | 4 ++-- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/mithril-aggregator/src/artifact_builder/dummy_artifact.rs b/mithril-aggregator/src/artifact_builder/dummy_artifact.rs index 49129a6afb4..c113a64377c 100644 --- a/mithril-aggregator/src/artifact_builder/dummy_artifact.rs +++ b/mithril-aggregator/src/artifact_builder/dummy_artifact.rs @@ -1,5 +1,3 @@ -use std::marker::PhantomData; - use async_trait::async_trait; use mithril_common::{ entities::Certificate, @@ -12,24 +10,19 @@ use crate::artifact_builder::ArtifactBuilder; /// Dummy artifact #[derive(Serialize, Deserialize, PartialEq, Debug)] -pub struct DummyArtifact<'a> { +pub struct DummyArtifact { message: String, beacon: DummyBeacon, - phantom: PhantomData<&'a DummyBeacon>, } -impl<'a> DummyArtifact<'a> { +impl DummyArtifact { /// Dummy artifact factory pub fn new(message: String, beacon: DummyBeacon) -> Self { - Self { - message, - beacon, - phantom: PhantomData, - } + Self { message, beacon } } } -impl<'a> Artifact<'a> for DummyArtifact<'a> {} +impl Artifact for DummyArtifact {} /// A [DummyArtifact] builder pub struct DummyArtifactBuilder {} @@ -48,9 +41,9 @@ impl Default for DummyArtifactBuilder { } #[async_trait] -impl<'a> ArtifactBuilder<'a, DummyBeacon, DummyArtifact<'a>> for DummyArtifactBuilder { +impl ArtifactBuilder for DummyArtifactBuilder { async fn compute_artifact( - &'a self, + &self, beacon: DummyBeacon, certificate: &Certificate, ) -> StdResult { diff --git a/mithril-aggregator/src/artifact_builder/interface.rs b/mithril-aggregator/src/artifact_builder/interface.rs index 32c52a93ed8..28d8a669432 100644 --- a/mithril-aggregator/src/artifact_builder/interface.rs +++ b/mithril-aggregator/src/artifact_builder/interface.rs @@ -5,13 +5,17 @@ use mithril_common::{ StdResult, }; +#[cfg(test)] +use mockall::automock; + /// ArtifactBuilder is trait for building an artifact +#[cfg_attr(test, automock)] #[async_trait] -pub trait ArtifactBuilder<'a, U, W> +pub trait ArtifactBuilder: Send + Sync where U: Beacon, - W: Artifact<'a>, + W: Artifact, { /// Compute an artifact - async fn compute_artifact(&'a self, beacon: U, certificate: &Certificate) -> StdResult; + async fn compute_artifact(&self, beacon: U, certificate: &Certificate) -> StdResult; } diff --git a/mithril-common/src/signable_builder/interface.rs b/mithril-common/src/signable_builder/interface.rs index a6675e930ac..206854db015 100644 --- a/mithril-common/src/signable_builder/interface.rs +++ b/mithril-common/src/signable_builder/interface.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Serialize}; use std::fmt::Debug; use crate::{entities::ProtocolMessage, StdResult}; @@ -14,7 +14,7 @@ pub trait Signable: Send + Sync { } /// Artifact is a trait for types that represent signed artifacts -pub trait Artifact<'a>: Serialize + Deserialize<'a> + PartialEq + Debug {} +pub trait Artifact: Serialize + DeserializeOwned + PartialEq + Debug + Send + Sync {} /// SignableBuilder is trait for building a signable for a beacon #[async_trait] From 25e0b7a7ec7da29b262acdb45c9cd0934d044a31 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Raynaud Date: Fri, 28 Apr 2023 16:15:11 +0200 Subject: [PATCH 2/5] Implement Mithril Stake Distribution Artifact Builder in aggregator --- .../mithril_stake_distribution.rs | 81 +++++++++++++++++++ .../src/artifact_builder/mod.rs | 2 + 2 files changed, 83 insertions(+) create mode 100644 mithril-aggregator/src/artifact_builder/mithril_stake_distribution.rs diff --git a/mithril-aggregator/src/artifact_builder/mithril_stake_distribution.rs b/mithril-aggregator/src/artifact_builder/mithril_stake_distribution.rs new file mode 100644 index 00000000000..da1326d0d5b --- /dev/null +++ b/mithril-aggregator/src/artifact_builder/mithril_stake_distribution.rs @@ -0,0 +1,81 @@ +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::RwLock; + +use super::ArtifactBuilder; +use crate::MultiSigner; +use mithril_common::{ + entities::{Certificate, Epoch, SignerWithStake}, + signable_builder::Artifact, + StdResult, +}; + +/// Mithril Stake Distribution +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] +pub struct MithrilStakeDistribution { + signers_with_stake: Vec, +} + +impl MithrilStakeDistribution { + /// MithrilStakeDistribution artifact factory + pub fn new(signers_with_stake: Vec) -> Self { + Self { signers_with_stake } + } +} + +impl Artifact for MithrilStakeDistribution {} + +/// A [MithrilStakeDistributionArtifact] builder +pub struct MithrilStakeDistributionArtifactBuilder { + multi_signer: Arc>, +} + +impl MithrilStakeDistributionArtifactBuilder { + /// MithrilStakeDistribution artifact builder factory + pub fn new(multi_signer: Arc>) -> Self { + Self { multi_signer } + } +} + +#[async_trait] +impl ArtifactBuilder for MithrilStakeDistributionArtifactBuilder { + async fn compute_artifact( + &self, + _beacon: Epoch, + _certificate: &Certificate, + ) -> StdResult { + let multi_signer = self.multi_signer.read().await; + Ok(MithrilStakeDistribution::new( + multi_signer.get_signers_with_stake().await?, + )) + } +} + +#[cfg(test)] +mod tests { + use mithril_common::test_utils::fake_data; + + use super::*; + + use crate::multi_signer::MockMultiSigner; + + #[tokio::test] + async fn test_compute_artifact() { + let signers_with_stake = fake_data::signers_with_stakes(5); + let signers_with_stake_clone = signers_with_stake.clone(); + let certificate = fake_data::certificate("cert-123".to_string()); + let mut mock_multi_signer = MockMultiSigner::new(); + mock_multi_signer + .expect_get_signers_with_stake() + .return_once(move || Ok(signers_with_stake_clone)); + let mithril_stake_distribution_artifact_builder = + MithrilStakeDistributionArtifactBuilder::new(Arc::new(RwLock::new(mock_multi_signer))); + let artifact = mithril_stake_distribution_artifact_builder + .compute_artifact(Epoch(1), &certificate) + .await + .unwrap(); + let artifact_expected = MithrilStakeDistribution::new(signers_with_stake); + assert_eq!(artifact_expected, artifact); + } +} diff --git a/mithril-aggregator/src/artifact_builder/mod.rs b/mithril-aggregator/src/artifact_builder/mod.rs index 6e37fb61c4d..22d172f6890 100644 --- a/mithril-aggregator/src/artifact_builder/mod.rs +++ b/mithril-aggregator/src/artifact_builder/mod.rs @@ -3,7 +3,9 @@ mod artifact_builder_service; mod dummy_artifact; mod interface; +mod mithril_stake_distribution; pub use artifact_builder_service::*; pub use dummy_artifact::*; pub use interface::*; +pub use mithril_stake_distribution::*; From ed5f8446b2b53ac4f85e9b09b71dcbe10e931edd Mon Sep 17 00:00:00 2001 From: Jean-Philippe Raynaud Date: Fri, 28 Apr 2023 16:15:58 +0200 Subject: [PATCH 3/5] Update Artifact Builder Service in aggregator --- .../artifact_builder_service.rs | 82 +++++++++---------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/mithril-aggregator/src/artifact_builder/artifact_builder_service.rs b/mithril-aggregator/src/artifact_builder/artifact_builder_service.rs index 36ab822ba24..0a8c6b01cec 100644 --- a/mithril-aggregator/src/artifact_builder/artifact_builder_service.rs +++ b/mithril-aggregator/src/artifact_builder/artifact_builder_service.rs @@ -1,25 +1,31 @@ use std::sync::Arc; use mithril_common::{ - entities::{Certificate, SignedEntityType}, - signable_builder::{Artifact, DummyBeacon}, + entities::{Certificate, Epoch, SignedEntityType}, + signable_builder::Artifact, StdResult, }; -use crate::artifact_builder::{ArtifactBuilder, DummyArtifactBuilder}; +use crate::artifact_builder::ArtifactBuilder; + +use super::MithrilStakeDistribution; /// ArtifactBuilder Service -// TODO: temporary implementation pub struct ArtifactBuilderService { - dummy_artifact_builder: DummyArtifactBuilder, + mithril_stake_distribution_artifact_builder: + Arc>, } impl ArtifactBuilderService { /// ArtifactBuilderService factory #[allow(dead_code)] - pub fn new(dummy_artifact_builder: DummyArtifactBuilder) -> Self { + pub fn new( + mithril_stake_distribution_artifact_builder: Arc< + dyn ArtifactBuilder, + >, + ) -> Self { Self { - dummy_artifact_builder, + mithril_stake_distribution_artifact_builder, } } } @@ -33,20 +39,11 @@ impl ArtifactBuilderService { ) -> StdResult> { let artifact = match signed_entity_type { SignedEntityType::MithrilStakeDistribution(e) => Arc::new( - self.dummy_artifact_builder - .compute_artifact(DummyBeacon { epoch: e }, certificate) - .await?, - ), - SignedEntityType::CardanoStakeDistribution(e) => Arc::new( - self.dummy_artifact_builder - .compute_artifact(DummyBeacon { epoch: e }, certificate) - .await?, - ), - SignedEntityType::CardanoImmutableFilesFull(b) => Arc::new( - self.dummy_artifact_builder - .compute_artifact(DummyBeacon { epoch: b.epoch }, certificate) + self.mithril_stake_distribution_artifact_builder + .compute_artifact(e, certificate) .await?, ), + _ => todo!(), }; Ok(artifact) @@ -55,37 +52,36 @@ impl ArtifactBuilderService { #[cfg(test)] mod tests { - use mithril_common::entities::{Beacon, Epoch}; + use mithril_common::{entities::Epoch, test_utils::fake_data}; use super::*; - // TODO: temporary test - #[tokio::test] - async fn test_artifact_builder_service() { - let dummy_artifact_builder = DummyArtifactBuilder::default(); - let artifact_builder_service = ArtifactBuilderService::new(dummy_artifact_builder); - let certificate = Certificate::default(); + use crate::artifact_builder::MockArtifactBuilder; - let signed_entity_type_1 = SignedEntityType::MithrilStakeDistribution(Epoch(1)); - let artifact_1 = artifact_builder_service - .compute_artifact(signed_entity_type_1, &certificate) - .await - .unwrap(); + #[tokio::test] + async fn test_artifact_builder_service_mithril_stake_distribution() { + let signers_with_stake = fake_data::signers_with_stakes(5); + let mithril_stake_distribution_expected = MithrilStakeDistribution::new(signers_with_stake); + let mithril_stake_distribution_clone = mithril_stake_distribution_expected.clone(); + let mut mock_mithril_stake_distribution_artifact_builder = + MockArtifactBuilder::::new(); + mock_mithril_stake_distribution_artifact_builder + .expect_compute_artifact() + .once() + .return_once(move |_, _| Ok(mithril_stake_distribution_clone)); - let signed_entity_type_2 = SignedEntityType::CardanoStakeDistribution(Epoch(0)); - let artifact_2 = artifact_builder_service - .compute_artifact(signed_entity_type_2, &certificate) - .await - .unwrap(); + let artifact_builder_service = + ArtifactBuilderService::new(Arc::new(mock_mithril_stake_distribution_artifact_builder)); + let certificate = Certificate::default(); - let signed_entity_type_3 = SignedEntityType::CardanoImmutableFilesFull(Beacon::default()); - let artifact_3 = artifact_builder_service - .compute_artifact(signed_entity_type_3, &certificate) + let signed_entity_type = SignedEntityType::MithrilStakeDistribution(Epoch(1)); + let artifact = artifact_builder_service + .compute_artifact(signed_entity_type, &certificate) .await .unwrap(); - - assert_ne!(artifact_1, artifact_2); - assert_ne!(artifact_1, artifact_3); - assert_eq!(artifact_2, artifact_3); + assert_eq!( + serde_json::to_string(&mithril_stake_distribution_expected).unwrap(), + serde_json::to_string(&artifact).unwrap() + ); } } From a2e61eeb6e556caaa6d526bb89af95246992775b Mon Sep 17 00:00:00 2001 From: Jean-Philippe Raynaud Date: Fri, 28 Apr 2023 16:16:35 +0200 Subject: [PATCH 4/5] Wire Mithril Stake Distribution Artifact Builder in dependencies --- .../src/dependency_injection/builder.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mithril-aggregator/src/dependency_injection/builder.rs b/mithril-aggregator/src/dependency_injection/builder.rs index 49b974cd1e8..4c9eadbb032 100644 --- a/mithril-aggregator/src/dependency_injection/builder.rs +++ b/mithril-aggregator/src/dependency_injection/builder.rs @@ -32,7 +32,7 @@ use tokio::{ use warp::Filter; use crate::{ - artifact_builder::{ArtifactBuilderService, DummyArtifactBuilder}, + artifact_builder::{ArtifactBuilderService, MithrilStakeDistributionArtifactBuilder}, certifier_service::{CertifierService, MithrilCertifierService}, configuration::{ExecutionEnvironment, LIST_SNAPSHOTS_MAX_ITEMS}, database::provider::{ @@ -897,9 +897,12 @@ impl DependenciesBuilder { } async fn build_artifact_builder_service(&mut self) -> Result> { - let dummy_artifact_builder = DummyArtifactBuilder::new(); - let artifact_builder_service = - Arc::new(ArtifactBuilderService::new(dummy_artifact_builder)); + let multi_signer = self.get_multi_signer().await?; + let mithril_stake_distribution_artifact_builder = + Arc::new(MithrilStakeDistributionArtifactBuilder::new(multi_signer)); + let artifact_builder_service = Arc::new(ArtifactBuilderService::new( + mithril_stake_distribution_artifact_builder, + )); Ok(artifact_builder_service) } From d159daf7f4b3968529fbc9251da38d894f549930 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Raynaud Date: Tue, 2 May 2023 10:07:26 +0200 Subject: [PATCH 5/5] Bump crate version --- Cargo.lock | 2 +- mithril-aggregator/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f72b5e8d84d..2e1c5c2682f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2063,7 +2063,7 @@ dependencies = [ [[package]] name = "mithril-aggregator" -version = "0.3.7" +version = "0.3.8" dependencies = [ "async-trait", "chrono", diff --git a/mithril-aggregator/Cargo.toml b/mithril-aggregator/Cargo.toml index 02b0515df5e..16674429405 100644 --- a/mithril-aggregator/Cargo.toml +++ b/mithril-aggregator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-aggregator" -version = "0.3.7" +version = "0.3.8" description = "A Mithril Aggregator server" authors = { workspace = true } edition = { workspace = true }