Skip to content

Commit 34f5397

Browse files
committed
feat: compute and store the total number of SPOs in the Epoch service
1 parent 85a0017 commit 34f5397

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

mithril-aggregator/src/dependency_injection/builder.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,8 @@ impl DependenciesBuilder {
12531253
let epoch_settings_storer = self.get_epoch_settings_storer().await?;
12541254
let chain_observer = self.get_chain_observer().await?;
12551255
let era_checker = self.get_era_checker().await?;
1256+
let stake_distribution_service = self.get_stake_distribution_service().await?;
1257+
12561258
let epoch_settings = self.get_epoch_settings_configuration()?;
12571259
let network = self.configuration.get_network()?;
12581260
let allowed_discriminants = self.get_allowed_signed_entity_types_discriminants()?;
@@ -1264,6 +1266,7 @@ impl DependenciesBuilder {
12641266
verification_key_store,
12651267
chain_observer,
12661268
era_checker,
1269+
stake_distribution_service,
12671270
),
12681271
network,
12691272
allowed_discriminants,

mithril-aggregator/src/services/epoch_service.rs

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ use mithril_common::logging::LoggerExtensions;
1616
use mithril_common::protocol::{MultiSigner as ProtocolMultiSigner, SignerBuilder};
1717
use mithril_common::{CardanoNetwork, StdResult};
1818

19-
use crate::entities::AggregatorEpochSettings;
20-
use crate::{EpochSettingsStorer, VerificationKeyStorer};
19+
use crate::{
20+
entities::AggregatorEpochSettings, services::StakeDistributionService, EpochSettingsStorer,
21+
VerificationKeyStorer,
22+
};
2123

2224
/// Errors dedicated to the CertifierService.
2325
#[derive(Debug, Error)]
@@ -108,6 +110,9 @@ pub trait EpochService: Sync + Send {
108110

109111
/// Get the [SignedEntityConfig] for the current epoch.
110112
fn signed_entity_config(&self) -> StdResult<&SignedEntityConfig>;
113+
114+
/// Get the total number of SPOs for the current epoch.
115+
fn total_spo(&self) -> StdResult<&u32>;
111116
}
112117

113118
struct EpochData {
@@ -122,6 +127,7 @@ struct EpochData {
122127
current_signers: Vec<Signer>,
123128
next_signers: Vec<Signer>,
124129
signed_entity_config: SignedEntityConfig,
130+
total_spo: u32,
125131
}
126132

127133
struct ComputedEpochData {
@@ -137,6 +143,7 @@ pub struct EpochServiceDependencies {
137143
verification_key_store: Arc<dyn VerificationKeyStorer>,
138144
chain_observer: Arc<dyn ChainObserver>,
139145
era_checker: Arc<EraChecker>,
146+
stake_distribution_service: Arc<dyn StakeDistributionService>,
140147
}
141148

142149
impl EpochServiceDependencies {
@@ -146,12 +153,14 @@ impl EpochServiceDependencies {
146153
verification_key_store: Arc<dyn VerificationKeyStorer>,
147154
chain_observer: Arc<dyn ChainObserver>,
148155
era_checker: Arc<EraChecker>,
156+
stake_distribution_service: Arc<dyn StakeDistributionService>,
149157
) -> Self {
150158
Self {
151159
epoch_settings_storer,
152160
verification_key_store,
153161
chain_observer,
154162
era_checker,
163+
stake_distribution_service,
155164
}
156165
}
157166
}
@@ -166,6 +175,7 @@ pub struct MithrilEpochService {
166175
verification_key_store: Arc<dyn VerificationKeyStorer>,
167176
chain_observer: Arc<dyn ChainObserver>,
168177
era_checker: Arc<EraChecker>,
178+
stake_distribution_service: Arc<dyn StakeDistributionService>,
169179
network: CardanoNetwork,
170180
allowed_signed_entity_discriminants: BTreeSet<SignedEntityTypeDiscriminants>,
171181
logger: Logger,
@@ -188,6 +198,7 @@ impl MithrilEpochService {
188198
verification_key_store: dependencies.verification_key_store,
189199
chain_observer: dependencies.chain_observer,
190200
era_checker: dependencies.era_checker,
201+
stake_distribution_service: dependencies.stake_distribution_service,
191202
network,
192203
allowed_signed_entity_discriminants: allowed_discriminants,
193204
logger: logger.new_with_component_name::<Self>(),
@@ -204,6 +215,16 @@ impl MithrilEpochService {
204215
Ok(cardano_era)
205216
}
206217

218+
async fn get_total_spo(&self, epoch: Epoch) -> StdResult<u32> {
219+
let stake_distribution = self
220+
.stake_distribution_service
221+
.get_stake_distribution(epoch)
222+
.await
223+
.with_context(|| "Epoch service failed to obtain stake distribution")?;
224+
225+
Ok(stake_distribution.len() as u32)
226+
}
227+
207228
async fn get_signers_with_stake_at_epoch(
208229
&self,
209230
signer_retrieval_epoch: Epoch,
@@ -312,6 +333,8 @@ impl EpochService for MithrilEpochService {
312333
.clone(),
313334
};
314335

336+
let total_spo = self.get_total_spo(epoch).await?;
337+
315338
self.epoch_data = Some(EpochData {
316339
cardano_era,
317340
mithril_era,
@@ -324,6 +347,7 @@ impl EpochService for MithrilEpochService {
324347
current_signers,
325348
next_signers,
326349
signed_entity_config,
350+
total_spo,
327351
});
328352
self.computed_epoch_data = None;
329353

@@ -455,6 +479,10 @@ impl EpochService for MithrilEpochService {
455479
fn signed_entity_config(&self) -> StdResult<&SignedEntityConfig> {
456480
Ok(&self.unwrap_data()?.signed_entity_config)
457481
}
482+
483+
fn total_spo(&self) -> StdResult<&u32> {
484+
Ok(&self.unwrap_data()?.total_spo)
485+
}
458486
}
459487

460488
#[cfg(test)]
@@ -477,6 +505,7 @@ pub struct FakeEpochServiceBuilder {
477505
pub current_signers_with_stake: Vec<SignerWithStake>,
478506
pub next_signers_with_stake: Vec<SignerWithStake>,
479507
pub signed_entity_config: SignedEntityConfig,
508+
pub total_spo: u32,
480509
}
481510

482511
#[cfg(test)]
@@ -495,6 +524,7 @@ impl FakeEpochServiceBuilder {
495524
current_signers_with_stake: signers.clone(),
496525
next_signers_with_stake: signers,
497526
signed_entity_config: SignedEntityConfig::dummy(),
527+
total_spo: 0,
498528
}
499529
}
500530

@@ -530,6 +560,7 @@ impl FakeEpochServiceBuilder {
530560
current_signers,
531561
next_signers,
532562
signed_entity_config: self.signed_entity_config,
563+
total_spo: self.total_spo,
533564
}),
534565
computed_epoch_data: Some(ComputedEpochData {
535566
aggregate_verification_key: protocol_multi_signer
@@ -723,23 +754,39 @@ impl EpochService for FakeEpochService {
723754
fn signed_entity_config(&self) -> StdResult<&SignedEntityConfig> {
724755
Ok(&self.unwrap_data()?.signed_entity_config)
725756
}
757+
758+
fn total_spo(&self) -> StdResult<&u32> {
759+
Ok(&self.unwrap_data()?.total_spo)
760+
}
726761
}
727762

728763
#[cfg(test)]
729764
mod tests {
730765
use mithril_common::chain_observer::FakeObserver;
731-
use mithril_common::entities::{BlockNumber, CardanoTransactionsSigningConfig, PartyId};
766+
use mithril_common::entities::{
767+
BlockNumber, CardanoTransactionsSigningConfig, PartyId, StakeDistribution,
768+
};
732769
use mithril_common::era::SupportedEra;
733770
use mithril_common::test_utils::{fake_data, MithrilFixture, MithrilFixtureBuilder};
734771
use mithril_persistence::store::adapter::MemoryAdapter;
735772
use std::collections::{BTreeSet, HashMap};
736773

774+
use crate::services::MockStakeDistributionService;
737775
use crate::store::FakeEpochSettingsStorer;
738776
use crate::test_tools::TestLogger;
739777
use crate::VerificationKeyStore;
740778

741779
use super::*;
742780

781+
fn stake_distribution_with_given_number_of_spo(total_spo: u32) -> StakeDistribution {
782+
let mut stake_distribution: StakeDistribution = StakeDistribution::new();
783+
for i in 0..total_spo {
784+
let party_id = format!("party-id-{i}");
785+
stake_distribution.insert(party_id.clone(), 0);
786+
}
787+
stake_distribution
788+
}
789+
743790
#[derive(Debug, Clone, PartialEq)]
744791
struct ExpectedEpochData {
745792
cardano_era: String,
@@ -755,6 +802,7 @@ mod tests {
755802
current_signers: BTreeSet<Signer>,
756803
next_signers: BTreeSet<Signer>,
757804
signed_entity_config: SignedEntityConfig,
805+
total_spo: u32,
758806
}
759807

760808
#[derive(Debug, Clone, PartialEq)]
@@ -793,6 +841,7 @@ mod tests {
793841
current_signers: service.current_signers()?.clone().into_iter().collect(),
794842
next_signers: service.next_signers()?.clone().into_iter().collect(),
795843
signed_entity_config: service.signed_entity_config()?.clone(),
844+
total_spo: *service.total_spo()?,
796845
})
797846
}
798847
}
@@ -829,6 +878,7 @@ mod tests {
829878
stored_current_epoch_settings: AggregatorEpochSettings,
830879
stored_next_epoch_settings: AggregatorEpochSettings,
831880
stored_signer_registration_epoch_settings: AggregatorEpochSettings,
881+
total_spo: u32,
832882
}
833883

834884
impl EpochServiceBuilder {
@@ -855,6 +905,7 @@ mod tests {
855905
protocol_parameters: epoch_fixture.protocol_parameters(),
856906
cardano_transactions_signing_config: CardanoTransactionsSigningConfig::dummy(),
857907
},
908+
total_spo: 0,
858909
}
859910
}
860911

@@ -892,7 +943,14 @@ mod tests {
892943
));
893944
let chain_observer = FakeObserver::default();
894945
chain_observer.set_current_era(self.cardano_era).await;
895-
let era_checker = EraChecker::new(self.mithril_era, Epoch(1));
946+
947+
let era_checker = EraChecker::new(self.mithril_era, Epoch::default());
948+
949+
let stake_distribution = stake_distribution_with_given_number_of_spo(self.total_spo);
950+
let mut stake_distribution_service = MockStakeDistributionService::new();
951+
stake_distribution_service
952+
.expect_get_stake_distribution()
953+
.returning(move |_| Ok(stake_distribution.clone()));
896954

897955
MithrilEpochService::new(
898956
AggregatorEpochSettings {
@@ -904,6 +962,7 @@ mod tests {
904962
Arc::new(vkey_store),
905963
Arc::new(chain_observer),
906964
Arc::new(era_checker),
965+
Arc::new(stake_distribution_service),
907966
),
908967
self.network,
909968
self.allowed_discriminants,
@@ -936,6 +995,7 @@ mod tests {
936995
allowed_discriminants: SignedEntityConfig::dummy().allowed_discriminants,
937996
cardano_era: "CardanoEra".to_string(),
938997
mithril_era: SupportedEra::eras()[1],
998+
total_spo: 37,
939999
..EpochServiceBuilder::new(epoch, current_epoch_fixture.clone())
9401000
};
9411001

@@ -972,6 +1032,7 @@ mod tests {
9721032
current_signers: current_epoch_fixture.signers().into_iter().collect(),
9731033
next_signers: next_epoch_fixture.signers().into_iter().collect(),
9741034
signed_entity_config: SignedEntityConfig::dummy(),
1035+
total_spo: 37,
9751036
}
9761037
);
9771038
}
@@ -1188,6 +1249,7 @@ mod tests {
11881249
service.next_protocol_multi_signer().err(),
11891250
),
11901251
("signed_entity_config", service.signed_entity_config().err()),
1252+
("total_spo", service.total_spo().err()),
11911253
] {
11921254
let error =
11931255
res.unwrap_or_else(|| panic!("getting {name} should have returned an error"));
@@ -1223,6 +1285,7 @@ mod tests {
12231285
assert!(service.current_signers().is_ok());
12241286
assert!(service.next_signers().is_ok());
12251287
assert!(service.signed_entity_config().is_ok());
1288+
assert!(service.total_spo().is_ok());
12261289

12271290
for (name, res) in [
12281291
(

0 commit comments

Comments
 (0)