Skip to content

Commit 70dcce9

Browse files
committed
feat(aggregator): make synchroniser add an open message at process end
1 parent d63b82b commit 70dcce9

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

mithril-aggregator/src/services/certificate_chain_synchroniser/interface.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use async_trait::async_trait;
33
use mithril_common::StdResult;
44
use mithril_common::entities::Certificate;
55

6+
use crate::entities::OpenMessage;
7+
68
/// Define how to synchronize the certificate chain with a remote source
79
#[cfg_attr(test, mockall::automock)]
810
#[async_trait::async_trait]
@@ -35,3 +37,11 @@ pub trait SynchronizedCertificateStorer: Send + Sync {
3537
/// Get the latest genesis Certificate
3638
async fn get_latest_genesis(&self) -> StdResult<Option<Certificate>>;
3739
}
40+
41+
/// Define how to store the open message created at the end of the synchronization process
42+
#[cfg_attr(test, mockall::automock)]
43+
#[async_trait]
44+
pub trait OpenMessageStorer: Send + Sync {
45+
/// Store an open_message in the database
46+
async fn insert_or_replace_open_message(&self, open_message: OpenMessage) -> StdResult<()>;
47+
}

mithril-aggregator/src/services/certificate_chain_synchroniser/synchroniser_service.rs

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,28 @@
1515
//! 4. Store the fetched certificates in the database, from genesis to latest, for each certificate:
1616
//! - if it exists in the database, it is replaced
1717
//! - if it doesn't exist, it is inserted
18-
//! 5. End
18+
//! 5. Create a certified open message in the database, based on the latest certificate and with a
19+
//! MithrilStakeDistribution signed entity type
20+
//! 6. End
1921
//!
2022
use anyhow::{Context, anyhow};
2123
use async_trait::async_trait;
24+
use chrono::Utc;
2225
use slog::{Logger, debug, info};
2326
use std::collections::VecDeque;
2427
use std::sync::Arc;
2528

2629
use mithril_common::StdResult;
2730
use mithril_common::certificate_chain::CertificateVerifier;
2831
use mithril_common::crypto_helper::ProtocolGenesisVerifier;
29-
use mithril_common::entities::Certificate;
32+
use mithril_common::entities::{Certificate, SignedEntityType};
3033
use mithril_common::logging::LoggerExtensions;
3134

35+
use crate::entities::OpenMessage;
36+
3237
use super::{
33-
CertificateChainSynchronizer, RemoteCertificateRetriever, SynchronizedCertificateStorer,
38+
CertificateChainSynchronizer, OpenMessageStorer, RemoteCertificateRetriever,
39+
SynchronizedCertificateStorer,
3440
};
3541

3642
/// Service that synchronizes the certificate chain with a remote aggregator
@@ -39,6 +45,7 @@ pub struct MithrilCertificateChainSynchronizer {
3945
certificate_storer: Arc<dyn SynchronizedCertificateStorer>,
4046
certificate_verifier: Arc<dyn CertificateVerifier>,
4147
genesis_verifier: Arc<ProtocolGenesisVerifier>,
48+
open_message_storer: Arc<dyn OpenMessageStorer>,
4249
logger: Logger,
4350
}
4451

@@ -68,13 +75,15 @@ impl MithrilCertificateChainSynchronizer {
6875
certificate_storer: Arc<dyn SynchronizedCertificateStorer>,
6976
certificate_verifier: Arc<dyn CertificateVerifier>,
7077
genesis_verifier: Arc<ProtocolGenesisVerifier>,
78+
open_message_storer: Arc<dyn OpenMessageStorer>,
7179
logger: Logger,
7280
) -> Self {
7381
Self {
7482
remote_certificate_retriever,
7583
certificate_storer,
7684
certificate_verifier,
7785
genesis_verifier,
86+
open_message_storer,
7887
logger: logger.new_with_component_name::<Self>(),
7988
}
8089
}
@@ -164,13 +173,18 @@ impl CertificateChainSynchronizer for MithrilCertificateChainSynchronizer {
164173
anyhow!("Remote aggregator doesn't have a chain yet")
165174
.context("Failed to retrieve latest remote certificate details"),
166175
)?;
176+
let open_message = prepare_open_message_to_store(&starting_point);
167177
let remote_certificate_chain = self
168178
.retrieve_and_validate_remote_certificate_chain(starting_point)
169179
.await
170180
.with_context(|| "Failed to retrieve and validate remote certificate chain")?;
171181
self.store_certificate_chain(remote_certificate_chain)
172182
.await
173183
.with_context(|| "Failed to store remote retrieved certificate chain")?;
184+
self.open_message_storer
185+
.insert_or_replace_open_message(open_message)
186+
.await
187+
.with_context(|| "Failed to store open message when synchronizing certificate chain")?;
174188

175189
info!(
176190
self.logger,
@@ -180,6 +194,19 @@ impl CertificateChainSynchronizer for MithrilCertificateChainSynchronizer {
180194
}
181195
}
182196

197+
fn prepare_open_message_to_store(latest_certificate: &Certificate) -> OpenMessage {
198+
OpenMessage {
199+
epoch: latest_certificate.epoch,
200+
signed_entity_type: SignedEntityType::MithrilStakeDistribution(latest_certificate.epoch),
201+
protocol_message: latest_certificate.protocol_message.clone(),
202+
is_certified: true,
203+
is_expired: false,
204+
single_signatures: Vec::new(),
205+
created_at: Utc::now(),
206+
expires_at: None,
207+
}
208+
}
209+
183210
#[cfg(test)]
184211
mod tests {
185212
use anyhow::anyhow;
@@ -194,7 +221,9 @@ mod tests {
194221
mock_extensions::MockBuilder,
195222
};
196223

197-
use crate::services::{MockRemoteCertificateRetriever, MockSynchronizedCertificateStorer};
224+
use crate::services::{
225+
MockOpenMessageStorer, MockRemoteCertificateRetriever, MockSynchronizedCertificateStorer,
226+
};
198227
use crate::test_tools::TestLogger;
199228

200229
use super::*;
@@ -240,6 +269,7 @@ mod tests {
240269
Arc::new(ProtocolGenesisVerifier::from_verification_key(
241270
genesis_verification_key,
242271
)),
272+
Arc::new(MockOpenMessageStorer::new()),
243273
TestLogger::stdout(),
244274
)
245275
}
@@ -599,6 +629,8 @@ mod tests {
599629
}
600630

601631
mod synchronize_certificate_chain {
632+
use mockall::predicate::function;
633+
602634
use super::*;
603635

604636
fn build_synchroniser(
@@ -617,6 +649,17 @@ mod tests {
617649
.return_once(move || Ok(Some(latest)));
618650
}),
619651
certificate_verifier: fake_verifier(remote_chain),
652+
open_message_storer: MockBuilder::<MockOpenMessageStorer>::configure(|mock| {
653+
// Ensure that `store_open_message` is called
654+
let expected_msd_epoch = remote_chain.latest_certificate().epoch;
655+
mock.expect_insert_or_replace_open_message()
656+
.with(function(move |open_message: &OpenMessage| {
657+
open_message.signed_entity_type
658+
== SignedEntityType::MithrilStakeDistribution(expected_msd_epoch)
659+
}))
660+
.times(1..)
661+
.returning(|_| Ok(()));
662+
}),
620663
..MithrilCertificateChainSynchronizer::default_for_test()
621664
}
622665
}

0 commit comments

Comments
 (0)