Skip to content

Commit 5d48588

Browse files
committed
feat: compute and store the total stake in the Epoch service
1 parent a723278 commit 5d48588

File tree

1 file changed

+59
-19
lines changed

1 file changed

+59
-19
lines changed

mithril-aggregator/src/services/epoch_service.rs

Lines changed: 59 additions & 19 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,7 +219,7 @@ 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)
@@ -224,7 +228,9 @@ impl MithrilEpochService {
224228
format!("Epoch service failed to obtain the stake distribution for epoch: {epoch}")
225229
})?;
226230

227-
Ok(stake_distribution.len() as u32)
231+
let total_stake = stake_distribution.values().copied().sum::<u64>();
232+
233+
Ok((stake_distribution.len() as u32, total_stake))
228234
}
229235

230236
async fn get_signers_with_stake_at_epoch(
@@ -335,7 +341,7 @@ impl EpochService for MithrilEpochService {
335341
.clone(),
336342
};
337343

338-
let total_spo = self.get_total_spo(epoch).await?;
344+
let (total_spo, total_stake) = self.get_total_spo_and_total_stake(epoch).await?;
339345

340346
self.epoch_data = Some(EpochData {
341347
cardano_era,
@@ -350,6 +356,7 @@ impl EpochService for MithrilEpochService {
350356
next_signers,
351357
signed_entity_config,
352358
total_spo,
359+
total_stake,
353360
});
354361
self.computed_epoch_data = None;
355362

@@ -485,6 +492,10 @@ impl EpochService for MithrilEpochService {
485492
fn total_spo(&self) -> StdResult<&u32> {
486493
Ok(&self.unwrap_data()?.total_spo)
487494
}
495+
496+
fn total_stake(&self) -> StdResult<&u64> {
497+
Ok(&self.unwrap_data()?.total_stake)
498+
}
488499
}
489500

490501
#[cfg(test)]
@@ -508,6 +519,7 @@ pub struct FakeEpochServiceBuilder {
508519
pub next_signers_with_stake: Vec<SignerWithStake>,
509520
pub signed_entity_config: SignedEntityConfig,
510521
pub total_spo: u32,
522+
pub total_stake: u64,
511523
}
512524

513525
#[cfg(test)]
@@ -527,6 +539,7 @@ impl FakeEpochServiceBuilder {
527539
next_signers_with_stake: signers,
528540
signed_entity_config: SignedEntityConfig::dummy(),
529541
total_spo: 0,
542+
total_stake: 0,
530543
}
531544
}
532545

@@ -563,6 +576,7 @@ impl FakeEpochServiceBuilder {
563576
next_signers,
564577
signed_entity_config: self.signed_entity_config,
565578
total_spo: self.total_spo,
579+
total_stake: self.total_stake,
566580
}),
567581
computed_epoch_data: Some(ComputedEpochData {
568582
aggregate_verification_key: protocol_multi_signer
@@ -760,6 +774,10 @@ impl EpochService for FakeEpochService {
760774
fn total_spo(&self) -> StdResult<&u32> {
761775
Ok(&self.unwrap_data()?.total_spo)
762776
}
777+
778+
fn total_stake(&self) -> StdResult<&u64> {
779+
Ok(&self.unwrap_data()?.total_stake)
780+
}
763781
}
764782

765783
#[cfg(test)]
@@ -769,7 +787,9 @@ mod tests {
769787
BlockNumber, CardanoTransactionsSigningConfig, PartyId, StakeDistribution,
770788
};
771789
use mithril_common::era::SupportedEra;
772-
use mithril_common::test_utils::{fake_data, MithrilFixture, MithrilFixtureBuilder};
790+
use mithril_common::test_utils::{
791+
fake_data, MithrilFixture, MithrilFixtureBuilder, StakeDistributionGenerationMethod,
792+
};
773793
use mithril_persistence::store::adapter::MemoryAdapter;
774794
use std::collections::{BTreeSet, HashMap};
775795

@@ -780,13 +800,13 @@ mod tests {
780800

781801
use super::*;
782802

783-
fn stake_distribution_with_given_number_of_spo(total_spo: u32) -> StakeDistribution {
784-
let mut stake_distribution: StakeDistribution = StakeDistribution::new();
785-
for i in 0..total_spo {
786-
let party_id = format!("party-id-{i}");
787-
stake_distribution.insert(party_id.clone(), 0);
788-
}
789-
stake_distribution
803+
fn build_uniform_stake_distribution(total_spo: u32, stake_by_spo: u64) -> StakeDistribution {
804+
let fixture = MithrilFixtureBuilder::default()
805+
.with_signers(total_spo as usize)
806+
.with_stake_distribution(StakeDistributionGenerationMethod::Uniform(stake_by_spo))
807+
.build();
808+
809+
fixture.stake_distribution()
790810
}
791811

792812
#[derive(Debug, Clone, PartialEq)]
@@ -805,6 +825,7 @@ mod tests {
805825
next_signers: BTreeSet<Signer>,
806826
signed_entity_config: SignedEntityConfig,
807827
total_spo: u32,
828+
total_stake: u64,
808829
}
809830

810831
#[derive(Debug, Clone, PartialEq)]
@@ -844,6 +865,7 @@ mod tests {
844865
next_signers: service.next_signers()?.clone().into_iter().collect(),
845866
signed_entity_config: service.signed_entity_config()?.clone(),
846867
total_spo: *service.total_spo()?,
868+
total_stake: *service.total_stake()?,
847869
})
848870
}
849871
}
@@ -881,6 +903,7 @@ mod tests {
881903
stored_next_epoch_settings: AggregatorEpochSettings,
882904
stored_signer_registration_epoch_settings: AggregatorEpochSettings,
883905
total_spo: u32,
906+
total_stake: u64,
884907
}
885908

886909
impl EpochServiceBuilder {
@@ -907,7 +930,8 @@ mod tests {
907930
protocol_parameters: epoch_fixture.protocol_parameters(),
908931
cardano_transactions_signing_config: CardanoTransactionsSigningConfig::dummy(),
909932
},
910-
total_spo: 0,
933+
total_spo: 1,
934+
total_stake: 0,
911935
}
912936
}
913937

@@ -948,11 +972,23 @@ mod tests {
948972

949973
let era_checker = EraChecker::new(self.mithril_era, Epoch::default());
950974

951-
let stake_distribution = stake_distribution_with_given_number_of_spo(self.total_spo);
952-
let mut stake_distribution_service = MockStakeDistributionService::new();
953-
stake_distribution_service
954-
.expect_get_stake_distribution()
955-
.returning(move |_| Ok(stake_distribution.clone()));
975+
let stake_distribution_service = {
976+
assert!(
977+
self.total_stake % self.total_spo as u64 == 0,
978+
"'total_stake' must be a multiple of 'total_spo' to create a uniform stake distribution"
979+
);
980+
let stake_per_spo = self.total_stake / self.total_spo as u64;
981+
982+
let stake_distribution =
983+
build_uniform_stake_distribution(self.total_spo, stake_per_spo);
984+
985+
let mut stake_distribution_service = MockStakeDistributionService::new();
986+
stake_distribution_service
987+
.expect_get_stake_distribution()
988+
.returning(move |_| Ok(stake_distribution.clone()));
989+
990+
stake_distribution_service
991+
};
956992

957993
MithrilEpochService::new(
958994
AggregatorEpochSettings {
@@ -997,7 +1033,8 @@ mod tests {
9971033
allowed_discriminants: SignedEntityConfig::dummy().allowed_discriminants,
9981034
cardano_era: "CardanoEra".to_string(),
9991035
mithril_era: SupportedEra::eras()[1],
1000-
total_spo: 37,
1036+
total_spo: 40,
1037+
total_stake: 20_000_000,
10011038
..EpochServiceBuilder::new(epoch, current_epoch_fixture.clone())
10021039
};
10031040

@@ -1034,7 +1071,8 @@ mod tests {
10341071
current_signers: current_epoch_fixture.signers().into_iter().collect(),
10351072
next_signers: next_epoch_fixture.signers().into_iter().collect(),
10361073
signed_entity_config: SignedEntityConfig::dummy(),
1037-
total_spo: 37,
1074+
total_spo: 40,
1075+
total_stake: 20_000_000,
10381076
}
10391077
);
10401078
}
@@ -1252,6 +1290,7 @@ mod tests {
12521290
),
12531291
("signed_entity_config", service.signed_entity_config().err()),
12541292
("total_spo", service.total_spo().err()),
1293+
("total_stake", service.total_stake().err()),
12551294
] {
12561295
let error =
12571296
res.unwrap_or_else(|| panic!("getting {name} should have returned an error"));
@@ -1288,6 +1327,7 @@ mod tests {
12881327
assert!(service.next_signers().is_ok());
12891328
assert!(service.signed_entity_config().is_ok());
12901329
assert!(service.total_spo().is_ok());
1330+
assert!(service.total_stake().is_ok());
12911331

12921332
for (name, res) in [
12931333
(

0 commit comments

Comments
 (0)