@@ -15,7 +15,10 @@ import (
1515 "github.com/vechain/thor/v2/thor"
1616)
1717
18+ //
1819// State transition types
20+ //
21+
1922type EpochTransition struct {
2023 Block uint32
2124 Renewals []ValidatorRenewal
@@ -38,7 +41,7 @@ func (s *Staker) Housekeep(currentBlock uint32) (bool, map[thor.Address]*validat
3841
3942 logger .Info ("🏠performing housekeeping" , "block" , currentBlock )
4043
41- transition , err := s .ComputeEpochTransition (currentBlock )
44+ transition , err := s .computeEpochTransition (currentBlock )
4245 if err != nil {
4346 return false , nil , err
4447 }
@@ -47,7 +50,7 @@ func (s *Staker) Housekeep(currentBlock uint32) (bool, map[thor.Address]*validat
4750 return false , nil , nil
4851 }
4952
50- if err := s .ApplyEpochTransition (transition ); err != nil {
53+ if err := s .applyEpochTransition (transition ); err != nil {
5154 return false , nil , err
5255 }
5356
@@ -58,12 +61,9 @@ func (s *Staker) Housekeep(currentBlock uint32) (bool, map[thor.Address]*validat
5861 return true , activeValidators , nil
5962}
6063
61- // ComputeEpochTransition calculates all state changes needed for an epoch transition
62- func (s * Staker ) ComputeEpochTransition (currentBlock uint32 ) (* EpochTransition , error ) {
64+ // computeEpochTransition calculates all state changes needed for an epoch transition
65+ func (s * Staker ) computeEpochTransition (currentBlock uint32 ) (* EpochTransition , error ) {
6366 var err error
64- if currentBlock % epochLength != 0 {
65- return nil , nil // No transition needed
66- }
6767
6868 transition := & EpochTransition {Block : currentBlock }
6969
@@ -80,7 +80,7 @@ func (s *Staker) ComputeEpochTransition(currentBlock uint32) (*EpochTransition,
8080 }
8181
8282 // 3. Compute all activations
83- transition .ActivationCount , err = s .computeActivations (transition .ExitValidator != nil )
83+ transition .ActivationCount , err = s .computeActivationCount (transition .ExitValidator != nil )
8484 if err != nil {
8585 return nil , err
8686 }
@@ -156,7 +156,8 @@ func (s *Staker) computeExits(currentBlock uint32) (*thor.Address, error) {
156156 return nil , nil
157157}
158158
159- func (s * Staker ) computeActivations (hasValidatorExited bool ) (int64 , error ) {
159+ // computeActivationCount calculates how many validators can be activated
160+ func (s * Staker ) computeActivationCount (hasValidatorExited bool ) (int64 , error ) {
160161 // Calculate how many validators can be activated
161162 queuedSize , err := s .QueuedGroupSize ()
162163 if err != nil {
@@ -193,8 +194,8 @@ func (s *Staker) computeActivations(hasValidatorExited bool) (int64, error) {
193194 return queuedCount , nil
194195}
195196
196- // ApplyEpochTransition applies all computed changes
197- func (s * Staker ) ApplyEpochTransition (transition * EpochTransition ) error {
197+ // applyEpochTransition applies all computed changes
198+ func (s * Staker ) applyEpochTransition (transition * EpochTransition ) error {
198199 logger .Info ("applying epoch transition" , "block" , transition .Block )
199200
200201 // Apply renewals
@@ -243,8 +244,7 @@ func (s *Staker) ApplyEpochTransition(transition *EpochTransition) error {
243244 }
244245
245246 for range transition .ActivationCount {
246- _ , err := s .ActivateNextValidator (transition .Block , maxLeaderGroupSize )
247- if err != nil {
247+ if _ , err := s .ActivateNextValidator (transition .Block , maxLeaderGroupSize ); err != nil {
248248 return err
249249 }
250250 }
@@ -273,134 +273,27 @@ func (s *Staker) buildActiveValidatorsFromTransition(transition *EpochTransition
273273 return activeValidators
274274}
275275
276- // Transition activates the staker contract when sufficient validators are queued
277- func (s * Staker ) Transition (currentBlock uint32 ) (bool , error ) {
278- active , err := s .IsPoSActive ()
279- if err != nil {
280- return false , err
281- }
282- if active {
283- return false , nil
284- }
285-
286- maxProposers , err := s .params .Get (thor .KeyMaxBlockProposers )
287- if err != nil || maxProposers .Cmp (big .NewInt (0 )) == 0 {
288- maxProposers = big .NewInt (0 ).SetUint64 (thor .InitialMaxBlockProposers )
289- }
290-
291- queueSize , err := s .validationService .QueuedGroupSize ()
292- if err != nil {
293- return false , err
294- }
295-
296- // if the queue size is not AT LEAST 2/3 of the maxProposers, then return nil
297- minimum := big .NewFloat (0 ).SetInt (maxProposers )
298- minimum .Mul (minimum , big .NewFloat (2 ))
299- minimum .Quo (minimum , big .NewFloat (3 ))
300- if big .NewFloat (0 ).SetInt (queueSize ).Cmp (minimum ) < 0 {
301- return false , nil
302- }
303-
304- // Use existing activateValidators method for transition
305- ids , err := s .activateValidators (currentBlock )
306- if err != nil {
307- return false , err
308- }
309- logger .Info ("activated validations" , "count" , len (ids ))
310-
311- return true , nil
312- }
313-
314- // activateValidators is kept for the Transition method
315- func (s * Staker ) activateValidators (currentBlock uint32 ) ([]* thor.Address , error ) {
316- queuedSize , err := s .QueuedGroupSize ()
317- if err != nil {
318- return nil , err
319- }
320- leaderSize , err := s .LeaderGroupSize ()
321- if err != nil {
322- return nil , err
323- }
324- maxSize , err := s .params .Get (thor .KeyMaxBlockProposers )
325- if err != nil {
326- return nil , err
327- }
328- if leaderSize .Cmp (maxSize ) >= 0 {
329- return nil , nil
330- }
331-
332- // no one is in the queue
333- if queuedSize .Cmp (big .NewInt (0 )) <= 0 {
334- return nil , nil
335- }
336-
337- queuedCount := queuedSize .Int64 ()
338- leaderDelta := maxSize .Int64 () - leaderSize .Int64 ()
339- if leaderDelta > 0 {
340- if leaderDelta < queuedCount {
341- queuedCount = leaderDelta
342- }
343- } else {
344- return nil , nil
345- }
346-
347- activated := make ([]* thor.Address , queuedCount )
348- maxLeaderGroupSize , err := s .params .Get (thor .KeyMaxBlockProposers )
349- if err != nil {
350- return nil , err
351- }
352-
353- for i := int64 (0 ); i < queuedCount ; i ++ {
354- id , err := s .ActivateNextValidator (currentBlock , maxLeaderGroupSize )
355- if err != nil {
356- return nil , err
357- }
358- activated [i ] = id
359- }
360-
361- return activated , nil
362- }
363-
276+ // TODO this should be a public method, it's ever only used in the pause test
364277func (s * Staker ) ActivateNextValidator (currentBlk uint32 , maxLeaderGroupSize * big.Int ) (* thor.Address , error ) {
365- validatorID , val , err := s .validationService .NextToActivate (maxLeaderGroupSize )
278+ validatorID , err := s .validationService .NextToActivate (maxLeaderGroupSize )
366279 if err != nil {
367280 return nil , err
368281 }
369282 logger .Debug ("activating validator" , "validatorID" , validatorID , "block" , currentBlk )
370283
284+ // renew the current delegations aggregation
371285 aggRenew , err := s .aggregationService .Renew (* validatorID )
372286 if err != nil {
373287 return nil , err
374288 }
375289
376- // update the validator values
377- // TODO move this to the validatorservice at some point
378- validatorLocked := big .NewInt (0 ).Add (val .LockedVET , val .QueuedVET )
379- val .QueuedVET = big .NewInt (0 )
380- val .LockedVET = validatorLocked
381- // x2 multiplier for validator's stake
382- validatorWeight := big .NewInt (0 ).Mul (validatorLocked , validatorWeightMultiplier )
383- val .Weight = big .NewInt (0 ).Add (validatorWeight , aggRenew .NewLockedWeight )
384-
385- // update the validator statuses
386- val .Status = validation .StatusActive
387- val .Online = true
388- val .StartBlock = currentBlk
389- // add to the active list
390- added , err := s .validationService .AddLeaderGroup (* validatorID , val )
290+ // Activate the validator using the validation service
291+ validatorRenewal , err := s .validationService .ActivateValidator (* validatorID , currentBlk , aggRenew )
391292 if err != nil {
392293 return nil , err
393294 }
394- if ! added {
395- return nil , errors .New ("failed to add validator to active list" )
396- }
397295
398- validatorRenewal := & delta.Renewal {
399- NewLockedVET : val .LockedVET ,
400- NewLockedWeight : val .Weight ,
401- QueuedDecrease : val .LockedVET ,
402- QueuedDecreaseWeight : big .NewInt (0 ).Mul (val .LockedVET , validatorWeightMultiplier ), // Only decrease validator's own weight
403- }
296+ // Update global stats with both validator and delegation renewals
404297 if err = s .globalStatsService .UpdateTotals (validatorRenewal , aggRenew ); err != nil {
405298 return nil , err
406299 }
0 commit comments