Skip to content

Commit a4aa755

Browse files
authored
Merge pull request #720 from input-output-hk/ensemble/709/era_reader
add era reader
2 parents 84baa27 + ecf55b5 commit a4aa755

File tree

19 files changed

+997
-182
lines changed

19 files changed

+997
-182
lines changed
25.8 KB
Loading

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::EraReaderBootstrapAdapter, 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(EraReaderBootstrapAdapter)));
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::EraReaderBootstrapAdapter, 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(EraReaderBootstrapAdapter)));
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::EraReaderBootstrapAdapter, 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(EraReaderBootstrapAdapter)));
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(
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use async_trait::async_trait;
2+
3+
use crate::entities::Epoch;
4+
5+
use super::super::{EraMarker, EraReaderAdapter, SupportedEra};
6+
7+
/// The goal of the bootstrap adapter is to advertise for the first existing Era
8+
/// while it does not exist yet on any backend. This adapter is intended to be
9+
/// removed once Eras are effectively written in a backend.
10+
pub struct BootstrapAdapter;
11+
12+
#[async_trait]
13+
impl EraReaderAdapter for BootstrapAdapter {
14+
async fn read(&self) -> Result<Vec<EraMarker>, Box<dyn std::error::Error + Sync + Send>> {
15+
Ok(vec![EraMarker::new(
16+
&SupportedEra::Thales.to_string(),
17+
Some(Epoch(1)),
18+
)])
19+
}
20+
}
21+
22+
#[cfg(test)]
23+
mod tests {
24+
use crate::era::SupportedEra;
25+
26+
use super::*;
27+
28+
#[tokio::test]
29+
async fn bootstrap_adapter() {
30+
let adapter = BootstrapAdapter;
31+
32+
assert_eq!(
33+
vec![EraMarker::new(
34+
&SupportedEra::dummy().to_string(),
35+
Some(Epoch(1))
36+
)],
37+
adapter
38+
.read()
39+
.await
40+
.expect("bootstrap adapter shall never fail")
41+
);
42+
}
43+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use std::error::Error;
2+
3+
use async_trait::async_trait;
4+
5+
use super::super::{EraMarker, EraReaderAdapter};
6+
7+
/// Dummy adapter is intended to be used in a test environment (end to end test)
8+
/// to simulate not yet activated Eras.
9+
#[derive(Default)]
10+
pub struct DummyAdapter {
11+
markers: Vec<EraMarker>,
12+
}
13+
14+
impl DummyAdapter {
15+
/// Tells what markers should be sent back by the adapter.
16+
pub fn set_markers(&mut self, markers: Vec<EraMarker>) {
17+
self.markers = markers;
18+
}
19+
}
20+
21+
#[async_trait]
22+
impl EraReaderAdapter for DummyAdapter {
23+
async fn read(&self) -> Result<Vec<EraMarker>, Box<dyn Error + Sync + Send>> {
24+
Ok(self.markers.clone())
25+
}
26+
}
27+
28+
#[cfg(test)]
29+
mod tests {
30+
use crate::entities::Epoch;
31+
32+
use super::super::super::SupportedEra;
33+
use super::*;
34+
35+
#[tokio::test]
36+
async fn empty_dummy_adapter() {
37+
let adapter = DummyAdapter::default();
38+
39+
assert!(adapter
40+
.read()
41+
.await
42+
.expect("dummy adapter shall not fail reading")
43+
.is_empty());
44+
}
45+
46+
#[tokio::test]
47+
async fn dummy_adapter_output() {
48+
let markers = vec![
49+
EraMarker::new("one", Some(Epoch(1))),
50+
EraMarker::new(&SupportedEra::dummy().to_string(), None),
51+
EraMarker::new(&SupportedEra::dummy().to_string(), Some(Epoch(10))),
52+
];
53+
54+
let mut adapter = DummyAdapter::default();
55+
adapter.set_markers(markers.clone());
56+
57+
assert_eq!(
58+
markers,
59+
adapter
60+
.read()
61+
.await
62+
.expect("dummy adapter shall not fail reading")
63+
);
64+
}
65+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//! Module dedicated to EraReaderAdapter implementations.
2+
mod bootstrap;
3+
mod dummy;
4+
5+
pub use bootstrap::BootstrapAdapter as EraReaderBootstrapAdapter;
6+
pub use dummy::DummyAdapter as EraReaderDummyAdapter;

0 commit comments

Comments
 (0)