@@ -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
118121struct 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
133137struct 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