@@ -12,6 +12,7 @@ import (
1212 "github.com/attestantio/go-eth2-client/http"
1313 "github.com/attestantio/go-eth2-client/spec"
1414 "github.com/attestantio/go-eth2-client/spec/altair"
15+ "github.com/attestantio/go-eth2-client/spec/electra"
1516 "github.com/attestantio/go-eth2-client/spec/phase0"
1617 "github.com/pkg/errors"
1718
@@ -55,7 +56,8 @@ func (p *BeaconState) Run(
5556 valKeyToIndex map [string ]uint64 ,
5657 relayRewards * big.Int ,
5758 validatorIndexToWithdrawalAmount map [uint64 ]* big.Int ,
58- proposerTips map [uint64 ]* big.Int ) error {
59+ proposerTips map [uint64 ]* big.Int ,
60+ validatorIndexToProcessedConsolidation map [uint64 ][]* electra.PendingConsolidation ) error {
5961
6062 if currentBeaconState == nil || prevBeaconState == nil {
6163 return errors .New ("current or previous beacon state is nil" )
@@ -89,7 +91,8 @@ func (p *BeaconState) Run(
8991 activeValidatorIndexes ,
9092 currentBeaconState ,
9193 prevBeaconState ,
92- validatorIndexToWithdrawalAmount )
94+ validatorIndexToWithdrawalAmount ,
95+ validatorIndexToProcessedConsolidation )
9396
9497 if err != nil {
9598 return errors .Wrap (err , "error populating participation and balance" )
@@ -179,7 +182,8 @@ func (p *BeaconState) PopulateParticipationAndBalance(
179182 activeValidatorIndexes []uint64 ,
180183 beaconState * spec.VersionedBeaconState ,
181184 prevBeaconState * spec.VersionedBeaconState ,
182- validatorIndexToWithdrawalAmount map [uint64 ]* big.Int ) (schemas.ValidatorPerformanceMetrics , error ) {
185+ validatorIndexToWithdrawalAmount map [uint64 ]* big.Int ,
186+ validatorIndexToProcessedConsolidation map [uint64 ][]* electra.PendingConsolidation ) (schemas.ValidatorPerformanceMetrics , error ) {
183187
184188 metrics := schemas.ValidatorPerformanceMetrics {
185189 EarnedBalance : big .NewInt (0 ),
@@ -212,7 +216,8 @@ func (p *BeaconState) PopulateParticipationAndBalance(
212216 activeValidatorIndexes ,
213217 prevBeaconState ,
214218 beaconState ,
215- validatorIndexToWithdrawalAmount )
219+ validatorIndexToWithdrawalAmount ,
220+ validatorIndexToProcessedConsolidation )
216221
217222 if err != nil {
218223 return schemas.ValidatorPerformanceMetrics {}, err
@@ -340,11 +345,13 @@ func (p *BeaconState) GetValidatorsWithLessBalance(
340345 activeValidatorIndexes []uint64 ,
341346 prevBeaconState * spec.VersionedBeaconState ,
342347 currentBeaconState * spec.VersionedBeaconState ,
343- validatorIndexToWithdrawalAmount map [uint64 ]* big.Int ) ([]uint64 , * big.Int , * big.Int , error ) {
348+ validatorIndexToWithdrawalAmount map [uint64 ]* big.Int ,
349+ validatorIndexToProcessedConsolidation map [uint64 ][]* electra.PendingConsolidation ) ([]uint64 , * big.Int , * big.Int , error ) {
344350
345351 prevEpoch := GetSlot (prevBeaconState ) / p .networkParameters .slotsInEpoch
346352 currEpoch := GetSlot (currentBeaconState ) / p .networkParameters .slotsInEpoch
347353 prevBalances := GetBalances (prevBeaconState )
354+ prevValidators := GetValidators (prevBeaconState )
348355 currBalances := GetBalances (currentBeaconState )
349356
350357 if (prevEpoch + 1 ) != currEpoch {
@@ -367,9 +374,18 @@ func (p *BeaconState) GetValidatorsWithLessBalance(
367374
368375 prevEpochValBalance := big .NewInt (0 ).SetUint64 (prevBalances [valIdx ])
369376 currentEpochValBalance := big .NewInt (0 ).SetUint64 (currBalances [valIdx ])
377+ // Check if there is a withdrawal amount and add it to the balance
370378 if valWithdrawalAmount , ok := validatorIndexToWithdrawalAmount [valIdx ]; ok {
371379 currentEpochValBalance .Add (currentEpochValBalance , valWithdrawalAmount )
372380 }
381+ // Check if there are consolidations and substract source effective balance
382+ if consolidations , ok := validatorIndexToProcessedConsolidation [valIdx ]; ok {
383+ for _ , consolidation := range consolidations {
384+ sourceBalance := big .NewInt (0 ).SetUint64 (uint64 (prevValidators [consolidation .SourceIndex ].EffectiveBalance ))
385+ currentEpochValBalance .Sub (currentEpochValBalance , sourceBalance )
386+ }
387+ }
388+
373389 delta := big .NewInt (0 ).Sub (currentEpochValBalance , prevEpochValBalance )
374390
375391 if delta .Cmp (big .NewInt (0 )) == - 1 {
@@ -474,6 +490,43 @@ func isBitSet(input uint8, n int) bool {
474490 return (input & (1 << n )) > uint8 (0 )
475491}
476492
493+ func GetProcessedConsolidations (
494+ prevBeaconState * spec.VersionedBeaconState ,
495+ currentBeaconState * spec.VersionedBeaconState ,
496+ ) (map [uint64 ][]* electra.PendingConsolidation , error ) {
497+ consolidations := make (map [uint64 ][]* electra.PendingConsolidation )
498+
499+ validators := GetValidators (currentBeaconState )
500+ prevPendingConsolidations := GetPendingConsolidations (prevBeaconState )
501+ currPendingConsolidations := GetPendingConsolidations (currentBeaconState )
502+
503+ if prevPendingConsolidations == nil || currPendingConsolidations == nil {
504+ return nil , errors .New ("state with nil pending consolidations found" )
505+ }
506+
507+ if len (validators ) == 0 {
508+ return consolidations , nil
509+ }
510+
511+ // Set of current pending consolidations
512+ currPendingConsolidationsSet := make (map [electra.PendingConsolidation ]bool )
513+ for _ , consolidation := range currPendingConsolidations {
514+ currPendingConsolidationsSet [* consolidation ] = true
515+ }
516+
517+ // If the consolidation is not in the current set, it was processed or source slashed
518+ for _ , consolidation := range prevPendingConsolidations {
519+ if _ , ok := currPendingConsolidationsSet [* consolidation ]; ! ok {
520+ sourceValidator := validators [consolidation .SourceIndex ]
521+ if sourceValidator .Slashed {
522+ continue
523+ }
524+ consolidations [uint64 (consolidation .TargetIndex )] = append (consolidations [uint64 (consolidation .TargetIndex )], consolidation )
525+ }
526+ }
527+ return consolidations , nil
528+ }
529+
477530func logMetrics (
478531 metrics schemas.ValidatorPerformanceMetrics ,
479532 poolName string ) {
@@ -632,3 +685,15 @@ func GetCurrentSyncCommittee(beaconState *spec.VersionedBeaconState) []phase0.BL
632685 }
633686 return pubKeys
634687}
688+
689+ func GetPendingConsolidations (beaconState * spec.VersionedBeaconState ) []* electra.PendingConsolidation {
690+ var pendingConsolidations []* electra.PendingConsolidation
691+ if beaconState .Electra != nil {
692+ pendingConsolidations = beaconState .Electra .PendingConsolidations
693+ } else if beaconState .Fulu != nil {
694+ pendingConsolidations = beaconState .Fulu .PendingConsolidations
695+ } else {
696+ log .Fatal ("Beacon state was empty" )
697+ }
698+ return pendingConsolidations
699+ }
0 commit comments