Skip to content

Commit 3fd4d50

Browse files
committed
add era reader in the Aggregator
1 parent fab2a97 commit 3fd4d50

File tree

8 files changed

+128
-32
lines changed

8 files changed

+128
-32
lines changed

mithril-aggregator/src/command_args.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ use mithril_common::{
1515
CardanoImmutableDigester, ImmutableFileSystemObserver,
1616
},
1717
entities::{Epoch, HexEncodedGenesisSecretKey},
18-
era::{EraChecker, SupportedEra},
18+
era::{adapters::BootstrapAdapter as BootstrapEraReaderAdapter, EraChecker, EraReader},
1919
store::{adapter::SQLiteAdapter, StakeStore},
20-
BeaconProviderImpl,
20+
BeaconProvider, BeaconProviderImpl,
2121
};
2222

2323
use crate::{
@@ -399,8 +399,14 @@ impl ServeCommand {
399399
));
400400

401401
// TODO: use EraReader when it is implemented to retrieve current era
402-
let current_era = SupportedEra::Thales;
403-
let era_checker = Arc::new(EraChecker::new(current_era));
402+
let era_reader = Arc::new(EraReader::new(Box::new(BootstrapEraReaderAdapter)));
403+
let era_epoch_token = era_reader
404+
.read_era_epoch_token(beacon_provider.get_current_beacon().await?.epoch)
405+
.await?;
406+
let era_checker = Arc::new(EraChecker::new(
407+
era_epoch_token.get_current_supported_era()?,
408+
era_epoch_token.get_current_epoch(),
409+
));
404410

405411
// Init dependency manager
406412
let dependency_manager = DependencyManager {
@@ -424,6 +430,7 @@ impl ServeCommand {
424430
signer_registerer: signer_registerer.clone(),
425431
signer_registration_round_opener: signer_registerer.clone(),
426432
era_checker: era_checker.clone(),
433+
era_reader: era_reader.clone(),
427434
};
428435
let dependency_manager = Arc::new(dependency_manager);
429436

mithril-aggregator/src/dependency.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use mithril_common::{
66
entities::{
77
Certificate, Epoch, ProtocolParameters, Signer, SignerWithStake, StakeDistribution,
88
},
9-
era::EraChecker,
9+
era::{EraChecker, EraReader},
1010
store::{StakeStore, StakeStorer},
1111
BeaconProvider,
1212
};
@@ -87,6 +87,9 @@ pub struct DependencyManager {
8787

8888
/// Era checker service
8989
pub era_checker: Arc<EraChecker>,
90+
91+
/// Era reader service
92+
pub era_reader: Arc<EraReader>,
9093
}
9194

9295
#[doc(hidden)]
@@ -269,10 +272,10 @@ pub mod tests {
269272
chain_observer::FakeObserver,
270273
crypto_helper::{key_encode_hex, ProtocolGenesisSigner},
271274
digesters::{DumbImmutableDigester, DumbImmutableFileObserver},
272-
era::{EraChecker, SupportedEra},
275+
era::{adapters::BootstrapAdapter as BootstrapEraReaderAdapter, EraChecker, EraReader},
273276
store::{adapter::MemoryAdapter, StakeStore},
274277
test_utils::fake_data,
275-
BeaconProviderImpl, CardanoNetwork,
278+
BeaconProvider, BeaconProviderImpl, CardanoNetwork,
276279
};
277280
use std::{path::PathBuf, sync::Arc};
278281
use tokio::sync::RwLock;
@@ -347,7 +350,15 @@ pub mod tests {
347350
chain_observer.clone(),
348351
verification_key_store.clone(),
349352
));
350-
let era_checker = Arc::new(EraChecker::new(SupportedEra::dummy()));
353+
let era_reader = Arc::new(EraReader::new(Box::new(BootstrapEraReaderAdapter)));
354+
let era_epoch_token = era_reader
355+
.read_era_epoch_token(beacon_provider.get_current_beacon().await.unwrap().epoch)
356+
.await
357+
.unwrap();
358+
let era_checker = Arc::new(EraChecker::new(
359+
era_epoch_token.get_current_supported_era().unwrap(),
360+
era_epoch_token.get_current_epoch(),
361+
));
351362

352363
let dependency_manager = DependencyManager {
353364
config,
@@ -370,6 +381,7 @@ pub mod tests {
370381
signer_registerer: signer_registerer.clone(),
371382
signer_registration_round_opener: signer_registerer,
372383
era_checker,
384+
era_reader,
373385
};
374386

375387
let config = AggregatorConfig::new(

mithril-aggregator/src/runtime/runner.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ pub trait AggregatorRunnerTrait: Sync + Send {
147147
ongoing_snapshot: &OngoingSnapshot,
148148
remote_locations: Vec<String>,
149149
) -> Result<Snapshot, RuntimeError>;
150+
151+
/// Update the EraChecker with EraReader information.
152+
async fn update_era_checker(&self, beacon: &Beacon) -> Result<(), RuntimeError>;
150153
}
151154

152155
/// The runner responsibility is to expose a code API for the state machine. It
@@ -614,6 +617,25 @@ impl AggregatorRunnerTrait for AggregatorRunner {
614617

615618
Ok(snapshot)
616619
}
620+
621+
async fn update_era_checker(&self, beacon: &Beacon) -> Result<(), RuntimeError> {
622+
let token = self
623+
.dependencies
624+
.era_reader
625+
.read_era_epoch_token(beacon.epoch)
626+
.await
627+
.map_err(|e| {
628+
RuntimeError::General(format!("Could not get Era information ('{e}')").into())
629+
})?;
630+
self.dependencies.era_checker.change_era(
631+
token.get_current_supported_era().map_err(|e| {
632+
RuntimeError::General(format!("Could not update EraChecker service ('{e}')").into())
633+
})?,
634+
token.get_current_epoch(),
635+
);
636+
637+
Ok(())
638+
}
617639
}
618640

619641
#[cfg(test)]
@@ -1148,4 +1170,19 @@ pub mod tests {
11481170
ongoing_snapshot.get_file_path()
11491171
);
11501172
}
1173+
1174+
#[tokio::test]
1175+
async fn test_update_era_checker() {
1176+
let (deps, config) = initialize_dependencies().await;
1177+
let beacon_provider = deps.beacon_provider.clone();
1178+
let era_checker = deps.era_checker.clone();
1179+
let mut beacon = beacon_provider.get_current_beacon().await.unwrap();
1180+
1181+
assert_eq!(beacon.epoch, era_checker.current_epoch());
1182+
let runner = AggregatorRunner::new(config, Arc::new(deps));
1183+
beacon.epoch += 1;
1184+
1185+
runner.update_era_checker(&beacon).await.unwrap();
1186+
assert_eq!(beacon.epoch, era_checker.current_epoch());
1187+
}
11511188
}

mithril-aggregator/src/runtime/state_machine.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ impl AggregatorRuntime {
222222
if maybe_current_beacon.is_none() || maybe_current_beacon.unwrap().epoch < new_beacon.epoch
223223
{
224224
self.runner.close_signer_registration_round().await?;
225+
self.runner.update_era_checker(&new_beacon).await?;
225226
self.runner.update_stake_distribution(&new_beacon).await?;
226227
self.runner
227228
.open_signer_registration_round(&new_beacon)
@@ -388,6 +389,11 @@ mod tests {
388389
.expect_is_certificate_chain_valid()
389390
.once()
390391
.returning(|| Ok(false));
392+
runner
393+
.expect_update_era_checker()
394+
.with(predicate::eq(fake_data::beacon()))
395+
.once()
396+
.returning(|_| Ok(()));
391397

392398
let mut runtime = init_runtime(
393399
Some(AggregatorState::Idle(IdleState {
@@ -435,6 +441,11 @@ mod tests {
435441
.expect_is_certificate_chain_valid()
436442
.once()
437443
.returning(|| Ok(true));
444+
runner
445+
.expect_update_era_checker()
446+
.with(predicate::eq(fake_data::beacon()))
447+
.once()
448+
.returning(|_| Ok(()));
438449

439450
let mut runtime = init_runtime(
440451
Some(AggregatorState::Idle(IdleState {

mithril-aggregator/tests/test_extensions/dependency.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ use mithril_common::chain_observer::FakeObserver;
99
use mithril_common::crypto_helper::{key_encode_hex, ProtocolGenesisSigner};
1010
use mithril_common::digesters::{DumbImmutableDigester, DumbImmutableFileObserver};
1111
use mithril_common::entities::ProtocolParameters;
12-
use mithril_common::era::{EraChecker, SupportedEra};
12+
use mithril_common::era::EraReader;
13+
use mithril_common::era::{adapters::BootstrapAdapter as BootstrapEraReaderAdapter, EraChecker};
1314
use mithril_common::store::adapter::MemoryAdapter;
1415
use mithril_common::store::StakeStore;
15-
use mithril_common::{BeaconProviderImpl, CardanoNetwork};
16+
use mithril_common::{BeaconProvider, BeaconProviderImpl, CardanoNetwork};
1617
use std::path::PathBuf;
1718
use std::sync::Arc;
1819
use tokio::sync::RwLock;
@@ -91,7 +92,15 @@ pub async fn initialize_dependencies(
9192
chain_observer.clone(),
9293
verification_key_store.clone(),
9394
));
94-
let era_checker = Arc::new(EraChecker::new(SupportedEra::dummy()));
95+
let era_reader = Arc::new(EraReader::new(Box::new(BootstrapEraReaderAdapter)));
96+
let era_epoch_token = era_reader
97+
.read_era_epoch_token(beacon_provider.get_current_beacon().await.unwrap().epoch)
98+
.await
99+
.unwrap();
100+
let era_checker = Arc::new(EraChecker::new(
101+
era_epoch_token.get_current_supported_era().unwrap(),
102+
era_epoch_token.get_current_epoch(),
103+
));
95104

96105
let dependency_manager = DependencyManager {
97106
config,
@@ -114,6 +123,7 @@ pub async fn initialize_dependencies(
114123
signer_registerer: signer_registerer.clone(),
115124
signer_registration_round_opener: signer_registerer,
116125
era_checker,
126+
era_reader,
117127
};
118128

119129
let config = AggregatorConfig::new(

mithril-common/src/era/adapters/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Module dedicated to [EraReaderAdapter] implementations.
1+
//! Module dedicated to EraReaderAdapter implementations.
22
mod bootstrap;
33
mod dummy;
44

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,45 @@
11
use std::sync::RwLock;
22

3+
use crate::entities::Epoch;
4+
35
use super::SupportedEra;
46

7+
struct SupportedEraStamp {
8+
era: SupportedEra,
9+
epoch: Epoch,
10+
}
11+
512
/// EraChecker allows the verification of the current era
613
pub struct EraChecker {
7-
current_era: RwLock<SupportedEra>,
14+
current_era_stamp: RwLock<SupportedEraStamp>,
815
}
916

1017
impl EraChecker {
1118
/// Era checker factory
12-
pub fn new(era: SupportedEra) -> Self {
19+
pub fn new(era: SupportedEra, epoch: Epoch) -> Self {
1320
Self {
14-
current_era: RwLock::new(era),
21+
current_era_stamp: RwLock::new(SupportedEraStamp { era, epoch }),
1522
}
1623
}
1724

1825
/// Retrieve the current era
1926
pub fn current_era(&self) -> SupportedEra {
20-
self.current_era.read().unwrap().to_owned()
27+
self.current_era_stamp.read().unwrap().era
28+
}
29+
30+
/// Retrieve the current Epoch
31+
pub fn current_epoch(&self) -> Epoch {
32+
self.current_era_stamp.read().unwrap().epoch
2133
}
2234

2335
/// Change the current era
24-
pub fn change_era(&self, new_era: SupportedEra) {
25-
let mut era = self.current_era.write().unwrap();
26-
*era = new_era;
36+
pub fn change_era(&self, new_era: SupportedEra, current_epoch: Epoch) {
37+
let new_stamp = SupportedEraStamp {
38+
era: new_era,
39+
epoch: current_epoch,
40+
};
41+
let mut stamp = self.current_era_stamp.write().unwrap();
42+
*stamp = new_stamp;
2743
}
2844

2945
/// Check if an era is active
@@ -39,16 +55,11 @@ mod tests {
3955
#[test]
4056
fn can_change_era() {
4157
let expected_era = SupportedEra::dummy();
42-
let era_checker = EraChecker::new(expected_era);
43-
era_checker.change_era(expected_era);
58+
let era_checker = EraChecker::new(expected_era, Epoch(1));
59+
era_checker.change_era(expected_era, Epoch(2));
4460

4561
assert_eq!(expected_era, era_checker.current_era());
46-
}
47-
48-
#[test]
49-
fn is_era_active_panics_when_current_era_not_set() {
50-
let expected_era = SupportedEra::dummy();
51-
let era_checker = EraChecker::new(expected_era);
52-
era_checker.is_era_active(expected_era);
62+
assert_eq!(Epoch(2), era_checker.current_epoch());
63+
assert!(era_checker.is_era_active(expected_era));
5364
}
5465
}

mithril-common/src/era/era_reader.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ use thiserror::Error;
66

77
use super::{supported_era::UnsupportedEraError, SupportedEra};
88

9-
/// Represents a tag of Era change.
9+
/// Value object that represents a tag of Era change.
1010
#[derive(Debug, Clone, PartialEq, Eq)]
1111
pub struct EraMarker {
12-
name: String,
13-
epoch: Option<Epoch>,
12+
/// Era name
13+
pub name: String,
14+
15+
/// Eventual information that advertises the Epoch of transition.
16+
pub epoch: Option<Epoch>,
1417
}
1518

1619
impl EraMarker {
@@ -25,7 +28,7 @@ impl EraMarker {
2528
/// Adapters are responsible of technically reading the information of
2629
/// [EraMarker]s from a backend.
2730
#[async_trait]
28-
pub trait EraReaderAdapter {
31+
pub trait EraReaderAdapter: Sync + Send {
2932
/// Read era markers from the underlying adapter.
3033
async fn read(&self) -> Result<Vec<EraMarker>, Box<dyn StdError>>;
3134
}
@@ -61,6 +64,11 @@ impl EraEpochToken {
6164
&self.current_era
6265
}
6366

67+
/// Return the epoch the Token has been created at
68+
pub fn get_current_epoch(&self) -> Epoch {
69+
self.current_epoch
70+
}
71+
6472
/// Try to cast the next [EraMarker] to a [SupportedEra]. If it fails, that
6573
/// means the coming Era will not be supported by this version of the
6674
/// software. This mechanism is used to issue a warning to the user asking

0 commit comments

Comments
 (0)