@@ -16,8 +16,10 @@ use mithril_common::logging::LoggerExtensions;
1616use mithril_common:: protocol:: { MultiSigner as ProtocolMultiSigner , SignerBuilder } ;
1717use 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
113118struct 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
127133struct 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
142149impl 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) ]
729764mod 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