Skip to content

Commit 93de39c

Browse files
committed
feat: compute and store the total stake in the Epoch service
1 parent 34f5397 commit 93de39c

File tree

1 file changed

+48
-14
lines changed

1 file changed

+48
-14
lines changed

mithril-aggregator/src/services/epoch_service.rs

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ pub trait EpochService: Sync + Send {
113113

114114
/// Get the total number of SPOs for the current epoch.
115115
fn total_spo(&self) -> StdResult<&u32>;
116+
117+
/// Get the total stake for the current epoch.
118+
fn total_stake(&self) -> StdResult<&u64>;
116119
}
117120

118121
struct EpochData {
@@ -128,6 +131,7 @@ struct EpochData {
128131
next_signers: Vec<Signer>,
129132
signed_entity_config: SignedEntityConfig,
130133
total_spo: u32,
134+
total_stake: u64,
131135
}
132136

133137
struct ComputedEpochData {
@@ -215,14 +219,16 @@ impl MithrilEpochService {
215219
Ok(cardano_era)
216220
}
217221

218-
async fn get_total_spo(&self, epoch: Epoch) -> StdResult<u32> {
222+
async fn get_total_spo_and_total_stake(&self, epoch: Epoch) -> StdResult<(u32, u64)> {
219223
let stake_distribution = self
220224
.stake_distribution_service
221225
.get_stake_distribution(epoch)
222226
.await
223227
.with_context(|| "Epoch service failed to obtain stake distribution")?;
224228

225-
Ok(stake_distribution.len() as u32)
229+
let total_stake = stake_distribution.values().copied().sum::<u64>();
230+
231+
Ok((stake_distribution.len() as u32, total_stake))
226232
}
227233

228234
async fn get_signers_with_stake_at_epoch(
@@ -333,7 +339,7 @@ impl EpochService for MithrilEpochService {
333339
.clone(),
334340
};
335341

336-
let total_spo = self.get_total_spo(epoch).await?;
342+
let (total_spo, total_stake) = self.get_total_spo_and_total_stake(epoch).await?;
337343

338344
self.epoch_data = Some(EpochData {
339345
cardano_era,
@@ -348,6 +354,7 @@ impl EpochService for MithrilEpochService {
348354
next_signers,
349355
signed_entity_config,
350356
total_spo,
357+
total_stake,
351358
});
352359
self.computed_epoch_data = None;
353360

@@ -483,6 +490,10 @@ impl EpochService for MithrilEpochService {
483490
fn total_spo(&self) -> StdResult<&u32> {
484491
Ok(&self.unwrap_data()?.total_spo)
485492
}
493+
494+
fn total_stake(&self) -> StdResult<&u64> {
495+
Ok(&self.unwrap_data()?.total_stake)
496+
}
486497
}
487498

488499
#[cfg(test)]
@@ -506,6 +517,7 @@ pub struct FakeEpochServiceBuilder {
506517
pub next_signers_with_stake: Vec<SignerWithStake>,
507518
pub signed_entity_config: SignedEntityConfig,
508519
pub total_spo: u32,
520+
pub total_stake: u64,
509521
}
510522

511523
#[cfg(test)]
@@ -525,6 +537,7 @@ impl FakeEpochServiceBuilder {
525537
next_signers_with_stake: signers,
526538
signed_entity_config: SignedEntityConfig::dummy(),
527539
total_spo: 0,
540+
total_stake: 0,
528541
}
529542
}
530543

@@ -561,6 +574,7 @@ impl FakeEpochServiceBuilder {
561574
next_signers,
562575
signed_entity_config: self.signed_entity_config,
563576
total_spo: self.total_spo,
577+
total_stake: self.total_stake,
564578
}),
565579
computed_epoch_data: Some(ComputedEpochData {
566580
aggregate_verification_key: protocol_multi_signer
@@ -758,6 +772,10 @@ impl EpochService for FakeEpochService {
758772
fn total_spo(&self) -> StdResult<&u32> {
759773
Ok(&self.unwrap_data()?.total_spo)
760774
}
775+
776+
fn total_stake(&self) -> StdResult<&u64> {
777+
Ok(&self.unwrap_data()?.total_stake)
778+
}
761779
}
762780

763781
#[cfg(test)]
@@ -767,7 +785,9 @@ mod tests {
767785
BlockNumber, CardanoTransactionsSigningConfig, PartyId, StakeDistribution,
768786
};
769787
use mithril_common::era::SupportedEra;
770-
use mithril_common::test_utils::{fake_data, MithrilFixture, MithrilFixtureBuilder};
788+
use mithril_common::test_utils::{
789+
fake_data, MithrilFixture, MithrilFixtureBuilder, StakeDistributionGenerationMethod,
790+
};
771791
use mithril_persistence::store::adapter::MemoryAdapter;
772792
use std::collections::{BTreeSet, HashMap};
773793

@@ -778,13 +798,19 @@ mod tests {
778798

779799
use super::*;
780800

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);
801+
fn build_stake_distribution(total_spo: u32, total_stake: u64) -> StakeDistribution {
802+
if total_stake % total_spo as u64 != 0 {
803+
panic!("'total_stake' must be a multiple of 'total_spo' to facilitate the creation of a uniform stake distribution");
786804
}
787-
stake_distribution
805+
806+
let fixture = MithrilFixtureBuilder::default()
807+
.with_signers(total_spo as usize)
808+
.with_stake_distribution(StakeDistributionGenerationMethod::Uniform(
809+
total_stake / total_spo as u64,
810+
))
811+
.build();
812+
813+
fixture.stake_distribution()
788814
}
789815

790816
#[derive(Debug, Clone, PartialEq)]
@@ -803,6 +829,7 @@ mod tests {
803829
next_signers: BTreeSet<Signer>,
804830
signed_entity_config: SignedEntityConfig,
805831
total_spo: u32,
832+
total_stake: u64,
806833
}
807834

808835
#[derive(Debug, Clone, PartialEq)]
@@ -842,6 +869,7 @@ mod tests {
842869
next_signers: service.next_signers()?.clone().into_iter().collect(),
843870
signed_entity_config: service.signed_entity_config()?.clone(),
844871
total_spo: *service.total_spo()?,
872+
total_stake: *service.total_stake()?,
845873
})
846874
}
847875
}
@@ -879,6 +907,7 @@ mod tests {
879907
stored_next_epoch_settings: AggregatorEpochSettings,
880908
stored_signer_registration_epoch_settings: AggregatorEpochSettings,
881909
total_spo: u32,
910+
total_stake: u64,
882911
}
883912

884913
impl EpochServiceBuilder {
@@ -905,7 +934,8 @@ mod tests {
905934
protocol_parameters: epoch_fixture.protocol_parameters(),
906935
cardano_transactions_signing_config: CardanoTransactionsSigningConfig::dummy(),
907936
},
908-
total_spo: 0,
937+
total_spo: 1,
938+
total_stake: 0,
909939
}
910940
}
911941

@@ -946,7 +976,7 @@ mod tests {
946976

947977
let era_checker = EraChecker::new(self.mithril_era, Epoch::default());
948978

949-
let stake_distribution = stake_distribution_with_given_number_of_spo(self.total_spo);
979+
let stake_distribution = build_stake_distribution(self.total_spo, self.total_stake);
950980
let mut stake_distribution_service = MockStakeDistributionService::new();
951981
stake_distribution_service
952982
.expect_get_stake_distribution()
@@ -995,7 +1025,8 @@ mod tests {
9951025
allowed_discriminants: SignedEntityConfig::dummy().allowed_discriminants,
9961026
cardano_era: "CardanoEra".to_string(),
9971027
mithril_era: SupportedEra::eras()[1],
998-
total_spo: 37,
1028+
total_spo: 40,
1029+
total_stake: 20_000_000,
9991030
..EpochServiceBuilder::new(epoch, current_epoch_fixture.clone())
10001031
};
10011032

@@ -1032,7 +1063,8 @@ mod tests {
10321063
current_signers: current_epoch_fixture.signers().into_iter().collect(),
10331064
next_signers: next_epoch_fixture.signers().into_iter().collect(),
10341065
signed_entity_config: SignedEntityConfig::dummy(),
1035-
total_spo: 37,
1066+
total_spo: 40,
1067+
total_stake: 20_000_000,
10361068
}
10371069
);
10381070
}
@@ -1250,6 +1282,7 @@ mod tests {
12501282
),
12511283
("signed_entity_config", service.signed_entity_config().err()),
12521284
("total_spo", service.total_spo().err()),
1285+
("total_stake", service.total_stake().err()),
12531286
] {
12541287
let error =
12551288
res.unwrap_or_else(|| panic!("getting {name} should have returned an error"));
@@ -1286,6 +1319,7 @@ mod tests {
12861319
assert!(service.next_signers().is_ok());
12871320
assert!(service.signed_entity_config().is_ok());
12881321
assert!(service.total_spo().is_ok());
1322+
assert!(service.total_stake().is_ok());
12891323

12901324
for (name, res) in [
12911325
(

0 commit comments

Comments
 (0)