Skip to content

Commit 49db028

Browse files
Alenarturmelclem
authored andcommitted
feat(aggregator): move & rework handle discrepancies
- run it at the end of the serve dependency container build - retrieve and save data from the network configuration provider instead of the local node configuration - update follower integration test to check that local protocol parameter configuration is not read, instead the configuration is read through the network configuration provider from the leader
1 parent 88b34c0 commit 49db028

File tree

5 files changed

+124
-83
lines changed

5 files changed

+124
-83
lines changed

mithril-aggregator/src/dependency_injection/builder/enablers/epoch.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ impl DependenciesBuilder {
6161
))
6262
};
6363

64-
//TODO handle discrepency here
65-
6664
Ok(network_configuration_provider)
6765
}
6866

mithril-aggregator/src/dependency_injection/builder/mod.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod protocol;
33
mod support;
44

55
use anyhow::Context;
6-
use slog::Logger;
6+
use slog::{Logger, debug};
77
use std::{path::PathBuf, sync::Arc};
88
use tokio::{
99
sync::{
@@ -45,10 +45,11 @@ use super::{
4545
GenesisCommandDependenciesContainer, Result, ToolsCommandDependenciesContainer,
4646
};
4747
use crate::{
48-
AggregatorConfig, AggregatorRunner, AggregatorRuntime, ImmutableFileDigestMapper,
49-
MetricsService, MithrilSignerRegistrationLeader, MultiSigner, ProtocolParametersRetriever,
50-
ServeCommandDependenciesContainer, SignerRegisterer, SignerRegistrationRoundOpener,
51-
SignerRegistrationVerifier, SingleSignatureAuthenticator, VerificationKeyStorer,
48+
AggregatorConfig, AggregatorRunner, AggregatorRuntime, EpochSettingsStorer,
49+
ImmutableFileDigestMapper, MetricsService, MithrilSignerRegistrationLeader, MultiSigner,
50+
ProtocolParametersRetriever, ServeCommandDependenciesContainer, SignerRegisterer,
51+
SignerRegistrationRoundOpener, SignerRegistrationVerifier, SingleSignatureAuthenticator,
52+
VerificationKeyStorer,
5253
configuration::ConfigurationSource,
5354
database::repository::{
5455
CertificateRepository, EpochSettingsStore, OpenMessageRepository, SignedEntityStorer,
@@ -411,6 +412,8 @@ impl DependenciesBuilder {
411412
metrics_service: self.get_metrics_service().await?,
412413
};
413414

415+
self.handle_discrepancies_at_startup().await?;
416+
414417
Ok(dependencies_manager)
415418
}
416419

@@ -527,6 +530,53 @@ impl DependenciesBuilder {
527530
Ok(dependencies)
528531
}
529532

533+
/// Look for discrepancies in stored data and fix them.
534+
///
535+
/// Fix discrepancies for:
536+
/// - epoch settings: ensure that the network configuration parameters for the three working epochs
537+
/// window are stored in the database (see [mithril_protocol_config::model::MithrilNetworkConfiguration])
538+
pub async fn handle_discrepancies_at_startup(&mut self) -> Result<()> {
539+
let logger = self.root_logger();
540+
let current_epoch = self
541+
.get_chain_observer()
542+
.await?
543+
.get_current_epoch()
544+
.await
545+
.map_err(|e| DependenciesBuilderError::Initialization {
546+
message: "cannot handle startup discrepancies: failed to retrieve current epoch."
547+
.to_string(),
548+
error: Some(e.into()),
549+
})?
550+
.ok_or(DependenciesBuilderError::Initialization {
551+
message: "cannot handle startup discrepancies: no epoch returned.".to_string(),
552+
error: None,
553+
})?;
554+
let network_configuration = self
555+
.get_mithril_network_configuration_provider()
556+
.await?
557+
.get_network_configuration(current_epoch)
558+
.await
559+
.map_err(|e| DependenciesBuilderError::Initialization {
560+
message: format!("cannot handle startup discrepancies: failed to retrieve network configuration for epoch {current_epoch}"),
561+
error: Some(e),
562+
})?;
563+
let epoch_settings_store = self.get_epoch_settings_store().await?;
564+
565+
debug!(
566+
logger,
567+
"Handle discrepancies at startup of epoch settings store, will record epoch settings from the configuration for epoch {current_epoch}";
568+
"network_configuration" => ?network_configuration,
569+
);
570+
epoch_settings_store
571+
.handle_discrepancies_at_startup(&network_configuration)
572+
.await
573+
.map_err(|e| DependenciesBuilderError::Initialization {
574+
message: "can not create aggregator runner".to_string(),
575+
error: Some(e),
576+
})?;
577+
Ok(())
578+
}
579+
530580
/// Remove the dependencies builder from memory to release Arc instances.
531581
pub async fn vanish(self) {
532582
self.drop_sqlite_connections().await;

mithril-aggregator/src/dependency_injection/builder/support/stores.rs

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use anyhow::Context;
2-
use slog::debug;
32
use std::sync::Arc;
43
use std::time::Duration;
54

@@ -11,11 +10,11 @@ use crate::database::repository::{
1110
OpenMessageRepository, SignedEntityStore, SignedEntityStorer, SignerRegistrationStore,
1211
SignerStore, StakePoolStore,
1312
};
14-
use crate::dependency_injection::{DependenciesBuilder, DependenciesBuilderError, Result};
13+
use crate::dependency_injection::{DependenciesBuilder, Result};
1514
use crate::get_dependency;
1615
use crate::{
17-
CExplorerSignerRetriever, EpochSettingsStorer, ImmutableFileDigestMapper,
18-
ProtocolParametersRetriever, SignersImporter, VerificationKeyStorer,
16+
CExplorerSignerRetriever, ImmutableFileDigestMapper, ProtocolParametersRetriever,
17+
SignersImporter, VerificationKeyStorer,
1918
};
2019

2120
impl DependenciesBuilder {
@@ -89,52 +88,15 @@ impl DependenciesBuilder {
8988
}
9089

9190
async fn build_epoch_settings_store(&mut self) -> Result<Arc<EpochSettingsStore>> {
92-
let logger = self.root_logger();
9391
let epoch_settings_store = EpochSettingsStore::new(
9492
self.get_sqlite_connection().await?,
9593
self.configuration.safe_epoch_retention_limit(),
9694
);
97-
let current_epoch = self
98-
.get_chain_observer()
99-
.await?
100-
.get_current_epoch()
101-
.await
102-
.map_err(|e| DependenciesBuilderError::Initialization {
103-
message: "cannot create aggregator runner: failed to retrieve current epoch."
104-
.to_string(),
105-
error: Some(e.into()),
106-
})?
107-
.ok_or(DependenciesBuilderError::Initialization {
108-
message: "cannot build aggregator runner: no epoch returned.".to_string(),
109-
error: None,
110-
})?;
111-
let retrieval_epoch = current_epoch
112-
.offset_to_signer_retrieval_epoch()
113-
.map_err(|e| DependenciesBuilderError::Initialization {
114-
message: format!("cannot create aggregator runner: failed to offset current epoch '{current_epoch}' to signer retrieval epoch."),
115-
error: Some(e.into()),
116-
})?;
117-
118-
let epoch_settings_configuration = self
119-
.configuration
120-
.get_leader_aggregator_epoch_settings_configuration()?;
121-
debug!(
122-
logger,
123-
"Handle discrepancies at startup of epoch settings store, will record epoch settings from the configuration for epoch {retrieval_epoch}";
124-
"epoch_settings_configuration" => ?epoch_settings_configuration,
125-
);
126-
epoch_settings_store
127-
.handle_discrepancies_at_startup(retrieval_epoch, &epoch_settings_configuration)
128-
.await
129-
.map_err(|e| DependenciesBuilderError::Initialization {
130-
message: "can not create aggregator runner".to_string(),
131-
error: Some(e),
132-
})?;
13395

13496
Ok(Arc::new(epoch_settings_store))
13597
}
13698

137-
/// Get a configured [EpochSettingsStorer].
99+
/// Get a configured [EpochSettingsStore].
138100
pub async fn get_epoch_settings_store(&mut self) -> Result<Arc<EpochSettingsStore>> {
139101
get_dependency!(self.epoch_settings_store)
140102
}

mithril-aggregator/src/store/epoch_settings_storer.rs

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
use anyhow::anyhow;
2+
use async_trait::async_trait;
13
#[cfg(test)]
24
use std::collections::HashMap;
3-
4-
use async_trait::async_trait;
5-
use mithril_common::StdResult;
65
#[cfg(test)]
76
use tokio::sync::RwLock;
87

8+
use mithril_common::StdResult;
99
use mithril_common::entities::{Epoch, ProtocolParameters};
10+
use mithril_protocol_config::model::MithrilNetworkConfiguration;
1011

1112
use crate::{entities::AggregatorEpochSettings, services::EpochPruningTask};
1213

@@ -43,14 +44,37 @@ pub trait EpochSettingsStorer:
4344
/// call and the epoch service call.
4445
async fn handle_discrepancies_at_startup(
4546
&self,
46-
current_epoch: Epoch,
47-
epoch_settings_configuration: &AggregatorEpochSettings,
47+
network_configuration: &MithrilNetworkConfiguration,
4848
) -> StdResult<()> {
49-
for epoch_offset in 0..=3 {
50-
let epoch = current_epoch + epoch_offset;
49+
for (epoch, epoch_configuration) in [
50+
(
51+
network_configuration.epoch.offset_to_signer_retrieval_epoch()?,
52+
&network_configuration.configuration_for_aggregation,
53+
),
54+
(
55+
network_configuration.epoch,
56+
&network_configuration.configuration_for_next_aggregation,
57+
),
58+
(
59+
network_configuration.epoch.offset_to_recording_epoch(),
60+
&network_configuration.configuration_for_registration,
61+
),
62+
] {
5163
if self.get_epoch_settings(epoch).await?.is_none() {
52-
self.save_epoch_settings(epoch, epoch_settings_configuration.clone())
53-
.await?;
64+
self.save_epoch_settings(
65+
epoch,
66+
AggregatorEpochSettings {
67+
protocol_parameters: epoch_configuration.protocol_parameters.clone(),
68+
cardano_transactions_signing_config: epoch_configuration
69+
.signed_entity_types_config
70+
.cardano_transactions
71+
.clone()
72+
.ok_or(anyhow!(
73+
"missing cardano transactions signing config for epoch {epoch}"
74+
))?,
75+
},
76+
)
77+
.await?;
5478
}
5579
}
5680

@@ -116,7 +140,8 @@ impl EpochPruningTask for FakeEpochSettingsStorer {
116140

117141
#[cfg(test)]
118142
mod tests {
119-
use mithril_common::entities::CardanoTransactionsSigningConfig;
143+
use std::collections::BTreeSet;
144+
120145
use mithril_common::test::double::Dummy;
121146

122147
use super::*;
@@ -178,40 +203,43 @@ mod tests {
178203
#[tokio::test]
179204
async fn test_handle_discrepancies_at_startup_should_complete_at_least_four_epochs() {
180205
let epoch_settings = AggregatorEpochSettings::dummy();
181-
let epoch_settings_new = AggregatorEpochSettings {
182-
protocol_parameters: ProtocolParameters {
183-
k: epoch_settings.protocol_parameters.k + 1,
184-
..epoch_settings.protocol_parameters
185-
},
186-
cardano_transactions_signing_config: CardanoTransactionsSigningConfig {
187-
step: epoch_settings.cardano_transactions_signing_config.step + 1,
188-
..epoch_settings.cardano_transactions_signing_config
189-
},
190-
};
191-
let epoch = Epoch(1);
192-
let store = FakeEpochSettingsStorer::new(vec![
193-
(epoch, epoch_settings.clone()),
194-
(epoch + 1, epoch_settings.clone()),
195-
]);
206+
let mut aggregation_epoch_settings = epoch_settings.clone();
207+
aggregation_epoch_settings.protocol_parameters.k += 15;
196208

209+
let mut next_aggregation_epoch_settings = epoch_settings.clone();
210+
next_aggregation_epoch_settings.protocol_parameters.k += 26;
211+
212+
let mut registration_epoch_settings = epoch_settings.clone();
213+
registration_epoch_settings.protocol_parameters.k += 37;
214+
215+
let epoch = Epoch(5);
216+
let store = FakeEpochSettingsStorer::new(vec![]);
197217
store
198-
.handle_discrepancies_at_startup(epoch, &epoch_settings_new)
218+
.handle_discrepancies_at_startup(&MithrilNetworkConfiguration {
219+
epoch,
220+
configuration_for_aggregation: aggregation_epoch_settings
221+
.clone()
222+
.into_network_configuration_for_epoch(BTreeSet::new()),
223+
configuration_for_next_aggregation: next_aggregation_epoch_settings
224+
.clone()
225+
.into_network_configuration_for_epoch(BTreeSet::new()),
226+
configuration_for_registration: registration_epoch_settings
227+
.clone()
228+
.into_network_configuration_for_epoch(BTreeSet::new()),
229+
})
199230
.await
200231
.unwrap();
201232

233+
let epoch_settings_stored = store.get_epoch_settings(epoch - 1).await.unwrap();
234+
assert_eq!(Some(aggregation_epoch_settings), epoch_settings_stored);
235+
202236
let epoch_settings_stored = store.get_epoch_settings(epoch).await.unwrap();
203-
assert_eq!(Some(epoch_settings.clone()), epoch_settings_stored);
237+
assert_eq!(Some(next_aggregation_epoch_settings), epoch_settings_stored);
204238

205239
let epoch_settings_stored = store.get_epoch_settings(epoch + 1).await.unwrap();
206-
assert_eq!(Some(epoch_settings.clone()), epoch_settings_stored);
240+
assert_eq!(Some(registration_epoch_settings), epoch_settings_stored);
207241

208242
let epoch_settings_stored = store.get_epoch_settings(epoch + 2).await.unwrap();
209-
assert_eq!(Some(epoch_settings_new.clone()), epoch_settings_stored);
210-
211-
let epoch_settings_stored = store.get_epoch_settings(epoch + 3).await.unwrap();
212-
assert_eq!(Some(epoch_settings_new.clone()), epoch_settings_stored);
213-
214-
let epoch_settings_stored = store.get_epoch_settings(epoch + 4).await.unwrap();
215243
assert!(epoch_settings_stored.is_none());
216244
}
217245
}

mithril-aggregator/tests/create_certificate_follower.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ async fn create_certificate_follower() {
117117
"create_certificate_follower",
118118
),
119119
leader_aggregator_endpoint: Some(leader_aggregator_http_server.url().to_string()),
120+
// Follower must retrieve parameters from the network configuration (today through the leader)
121+
// so this parameters should not be read
122+
protocol_parameters: None,
120123
..leader_configuration
121124
};
122125
let mut follower_tester = RuntimeTester::build(start_time_point, follower_configuration).await;

0 commit comments

Comments
 (0)