Skip to content

Commit 971b382

Browse files
authored
Merge pull request #2351 from input-output-hk/jpraynaud/2334-aggregator-slave-registration-mode
Feat: implement aggregator `slave` signer registration mode
2 parents 468de2d + 4c90983 commit 971b382

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3582
-1135
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ As a minor extension, we have adopted a slightly different versioning convention
1515

1616
- End support for **macOS x64 pre-built binaries** for the client CLI.
1717

18+
- **UNSTABLE** Implement a slave signer registration mode in the aggregator.
19+
1820
- **UNSTABLE** Cardano database incremental certification:
1921

2022
- Implement the client library for the the signed entity type `CardanoDatabase` (download and prove snapshot).

Cargo.lock

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-aggregator/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.7.10"
3+
version = "0.7.11"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }
@@ -69,6 +69,8 @@ tikv-jemallocator = { version = "0.6.0", optional = true }
6969

7070
[dev-dependencies]
7171
criterion = { version = "0.5.1", features = ["html_reports", "async_tokio"] }
72+
http = "1.2.0"
73+
httpmock = "0.7.0"
7274
mithril-common = { path = "../mithril-common", features = [
7375
"allow_skip_signer_certification",
7476
"test_tools",

mithril-aggregator/src/commands/serve_command.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ use crate::{dependency_injection::DependenciesBuilder, Configuration};
1515
pub struct ServeCommand {
1616
/// Server listening IP
1717
#[clap(long)]
18-
pub server_ip: Option<String>,
18+
server_ip: Option<String>,
1919

2020
/// Server TCP port
2121
#[clap(long)]
22-
pub server_port: Option<u16>,
22+
server_port: Option<u16>,
2323

2424
/// Directory to store snapshot
2525
/// Defaults to work folder
2626
#[clap(long)]
27-
pub snapshot_directory: Option<PathBuf>,
27+
snapshot_directory: Option<PathBuf>,
2828

2929
/// Disable immutables digests cache.
3030
#[clap(long)]
@@ -53,6 +53,14 @@ pub struct ServeCommand {
5353
/// Metrics HTTP server listening port.
5454
#[clap(long)]
5555
metrics_server_port: Option<u16>,
56+
57+
/// Master aggregator endpoint
58+
///
59+
/// This is the endpoint of the aggregator that will be used to fetch the latest epoch settings
60+
/// and store the signer registrations when the aggregator is running in a slave mode.
61+
/// If this is not set, the aggregator will run in a master mode.
62+
#[clap(long)]
63+
master_aggregator_endpoint: Option<String>,
5664
}
5765

5866
impl Source for ServeCommand {
@@ -121,6 +129,15 @@ impl Source for ServeCommand {
121129
Value::new(Some(&namespace), ValueKind::from(metrics_server_port)),
122130
);
123131
}
132+
if let Some(master_aggregator_endpoint) = self.master_aggregator_endpoint.clone() {
133+
result.insert(
134+
"master_aggregator_endpoint".to_string(),
135+
Value::new(
136+
Some(&namespace),
137+
ValueKind::from(Some(master_aggregator_endpoint)),
138+
),
139+
);
140+
}
124141

125142
Ok(result)
126143
}

mithril-aggregator/src/configuration.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ pub struct Configuration {
193193

194194
/// Time interval at which usage metrics are persisted in event database (in seconds).
195195
pub persist_usage_report_interval_in_seconds: u64,
196+
197+
// Master aggregator endpoint
198+
///
199+
/// This is the endpoint of the aggregator that will be used to fetch the latest epoch settings
200+
/// and store the signer registrations when the aggregator is running in a slave mode.
201+
/// If this is not set, the aggregator will run in a master mode.
202+
pub master_aggregator_endpoint: Option<String>,
196203
}
197204

198205
/// Uploader needed to copy the snapshot once computed.
@@ -283,6 +290,7 @@ impl Configuration {
283290
metrics_server_ip: "0.0.0.0".to_string(),
284291
metrics_server_port: 9090,
285292
persist_usage_report_interval_in_seconds: 10,
293+
master_aggregator_endpoint: None,
286294
}
287295
}
288296

@@ -375,6 +383,11 @@ impl Configuration {
375383
cardano_transactions_signing_config: self.cardano_transactions_signing_config.clone(),
376384
}
377385
}
386+
387+
/// Check if the aggregator is running in slave mode.
388+
pub fn is_slave_aggregator(&self) -> bool {
389+
self.master_aggregator_endpoint.is_some()
390+
}
378391
}
379392

380393
/// Default configuration with all the default values for configurations.
@@ -726,4 +739,24 @@ mod test {
726739
"Joined URL `{joined_url}`, does not contain subpath `{subpath_without_trailing_slash}`"
727740
);
728741
}
742+
743+
#[test]
744+
fn is_slave_aggregator_returns_true_when_in_slave_mode() {
745+
let config = Configuration {
746+
master_aggregator_endpoint: Some("some_endpoint".to_string()),
747+
..Configuration::new_sample()
748+
};
749+
750+
assert!(config.is_slave_aggregator());
751+
}
752+
753+
#[test]
754+
fn is_slave_aggregator_returns_false_when_in_master_mode() {
755+
let config = Configuration {
756+
master_aggregator_endpoint: None,
757+
..Configuration::new_sample()
758+
};
759+
760+
assert!(!config.is_slave_aggregator());
761+
}
729762
}

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
//! - redefine the actual categories so those miscellaneous enablers fit into them
66
77
use std::sync::Arc;
8+
use std::time::Duration;
89

910
use mithril_signed_entity_lock::SignedEntityTypeLock;
1011

1112
use crate::database::repository::CertificateRepository;
1213
use crate::dependency_injection::{DependenciesBuilder, Result};
13-
use crate::services::{MessageService, MithrilMessageService};
14+
use crate::services::{
15+
AggregatorClient, AggregatorHTTPClient, MessageService, MithrilMessageService,
16+
};
1417

1518
impl DependenciesBuilder {
1619
async fn build_signed_entity_lock(&mut self) -> Result<Arc<SignedEntityTypeLock>> {
@@ -34,10 +37,12 @@ impl DependenciesBuilder {
3437
));
3538
let signed_entity_storer = self.get_signed_entity_storer().await?;
3639
let immutable_file_digest_mapper = self.get_immutable_file_digest_mapper().await?;
40+
let epoch_service = self.get_epoch_service().await?;
3741
let service = MithrilMessageService::new(
3842
certificate_repository,
3943
signed_entity_storer,
4044
immutable_file_digest_mapper,
45+
epoch_service,
4146
);
4247

4348
Ok(Arc::new(service))
@@ -51,4 +56,31 @@ impl DependenciesBuilder {
5156

5257
Ok(self.message_service.as_ref().cloned().unwrap())
5358
}
59+
60+
/// build an [AggregatorClient]
61+
pub async fn build_master_aggregator_client(&mut self) -> Result<Arc<dyn AggregatorClient>> {
62+
let master_aggregator_endpoint = self
63+
.configuration
64+
.master_aggregator_endpoint
65+
.to_owned()
66+
.unwrap_or_default();
67+
let aggregator_client = AggregatorHTTPClient::new(
68+
master_aggregator_endpoint,
69+
None,
70+
self.get_api_version_provider().await?,
71+
Some(Duration::from_secs(30)),
72+
self.root_logger(),
73+
);
74+
75+
Ok(Arc::new(aggregator_client))
76+
}
77+
78+
/// Returns a master [AggregatorClient]
79+
pub async fn get_master_aggregator_client(&mut self) -> Result<Arc<dyn AggregatorClient>> {
80+
if self.master_aggregator_client.is_none() {
81+
self.master_aggregator_client = Some(self.build_master_aggregator_client().await?);
82+
}
83+
84+
Ok(self.master_aggregator_client.as_ref().cloned().unwrap())
85+
}
5486
}

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

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,14 @@ use crate::{
4444
file_uploaders::FileUploader,
4545
http_server::routes::router::{self, RouterConfig, RouterState},
4646
services::{
47-
CertifierService, MessageService, ProverService, SignedEntityService, Snapshotter,
47+
AggregatorClient, CertifierService, MessageService, MithrilSignerRegistrationSlave,
48+
ProverService, SignedEntityService, SignerSynchronizer, Snapshotter,
4849
StakeDistributionService, UpkeepService,
4950
},
5051
tools::GenesisToolsDependency,
5152
AggregatorConfig, AggregatorRunner, AggregatorRuntime, Configuration, DependencyContainer,
52-
ImmutableFileDigestMapper, MetricsService, MithrilSignerRegisterer, MultiSigner,
53+
ImmutableFileDigestMapper, MetricsService, MithrilSignerRegistrationMaster, MultiSigner,
54+
SignerRegisterer, SignerRegistrationRoundOpener, SignerRegistrationVerifier,
5355
SingleSignatureAuthenticator, VerificationKeyStorer,
5456
};
5557

@@ -147,8 +149,23 @@ pub struct DependenciesBuilder {
147149
/// Genesis signature verifier service.
148150
pub genesis_verifier: Option<Arc<ProtocolGenesisVerifier>>,
149151

152+
/// Mithril signer registration master service
153+
pub mithril_signer_registration_master: Option<Arc<MithrilSignerRegistrationMaster>>,
154+
155+
/// Mithril signer registration slave service
156+
pub mithril_signer_registration_slave: Option<Arc<MithrilSignerRegistrationSlave>>,
157+
150158
/// Signer registerer service
151-
pub mithril_registerer: Option<Arc<MithrilSignerRegisterer>>,
159+
pub signer_registerer: Option<Arc<dyn SignerRegisterer>>,
160+
161+
/// Signer synchronizer service
162+
pub signer_synchronizer: Option<Arc<dyn SignerSynchronizer>>,
163+
164+
/// Signer registration verifier
165+
pub signer_registration_verifier: Option<Arc<dyn SignerRegistrationVerifier>>,
166+
167+
/// Signer registration round opener service
168+
pub signer_registration_round_opener: Option<Arc<dyn SignerRegistrationRoundOpener>>,
152169

153170
/// Era checker service
154171
pub era_checker: Option<Arc<EraChecker>>,
@@ -218,6 +235,9 @@ pub struct DependenciesBuilder {
218235

219236
/// Metrics service
220237
pub metrics_service: Option<Arc<MetricsService>>,
238+
239+
/// Master aggregator client
240+
pub master_aggregator_client: Option<Arc<dyn AggregatorClient>>,
221241
}
222242

223243
impl DependenciesBuilder {
@@ -249,7 +269,12 @@ impl DependenciesBuilder {
249269
snapshotter: None,
250270
certificate_verifier: None,
251271
genesis_verifier: None,
252-
mithril_registerer: None,
272+
mithril_signer_registration_master: None,
273+
mithril_signer_registration_slave: None,
274+
signer_registerer: None,
275+
signer_synchronizer: None,
276+
signer_registration_verifier: None,
277+
signer_registration_round_opener: None,
253278
era_reader_adapter: None,
254279
era_checker: None,
255280
era_reader: None,
@@ -272,6 +297,7 @@ impl DependenciesBuilder {
272297
upkeep_service: None,
273298
single_signer_authenticator: None,
274299
metrics_service: None,
300+
master_aggregator_client: None,
275301
}
276302
}
277303

@@ -316,8 +342,10 @@ impl DependenciesBuilder {
316342
snapshotter: self.get_snapshotter().await?,
317343
certificate_verifier: self.get_certificate_verifier().await?,
318344
genesis_verifier: self.get_genesis_verifier().await?,
319-
signer_registerer: self.get_mithril_registerer().await?,
320-
signer_registration_round_opener: self.get_mithril_registerer().await?,
345+
signer_registerer: self.get_signer_registerer().await?,
346+
signer_synchronizer: self.get_signer_synchronizer().await?,
347+
signer_registration_verifier: self.get_signer_registration_verifier().await?,
348+
signer_registration_round_opener: self.get_signer_registration_round_opener().await?,
321349
era_checker: self.get_era_checker().await?,
322350
era_reader: self.get_era_reader().await?,
323351
event_transmitter: self.get_event_transmitter().await?,
@@ -339,6 +367,7 @@ impl DependenciesBuilder {
339367
upkeep_service: self.get_upkeep_service().await?,
340368
single_signer_authenticator: self.get_single_signature_authenticator().await?,
341369
metrics_service: self.get_metrics_service().await?,
370+
master_aggregator_client: self.get_master_aggregator_client().await?,
342371
};
343372

344373
Ok(dependency_manager)
@@ -348,7 +377,10 @@ impl DependenciesBuilder {
348377
pub async fn create_aggregator_runner(&mut self) -> Result<AggregatorRuntime> {
349378
let dependency_container = Arc::new(self.build_dependency_container().await?);
350379

351-
let config = AggregatorConfig::new(Duration::from_millis(self.configuration.run_interval));
380+
let config = AggregatorConfig::new(
381+
Duration::from_millis(self.configuration.run_interval),
382+
self.configuration.is_slave_aggregator(),
383+
);
352384
let runtime = AggregatorRuntime::new(
353385
config,
354386
None,

0 commit comments

Comments
 (0)