Skip to content

Commit fb32efb

Browse files
authored
Apply processed consolidations (#55)
* apply processed consolidations * Improve pendConsolidations checks, update map to use struct * Fix consolidation target balance using source effective balance
1 parent b810f4d commit fb32efb

File tree

3 files changed

+141
-8
lines changed

3 files changed

+141
-8
lines changed

metrics/beaconstate.go

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
477530
func 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+
}

metrics/beaconstate_test.go

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/attestantio/go-eth2-client/spec"
99
"github.com/attestantio/go-eth2-client/spec/altair"
10+
"github.com/attestantio/go-eth2-client/spec/electra"
1011
"github.com/attestantio/go-eth2-client/spec/phase0"
1112

1213
"github.com/stretchr/testify/require"
@@ -87,7 +88,9 @@ func Test_GetValidatorsWithLessBalance(t *testing.T) {
8788
[]uint64{0, 1, 2, 3},
8889
prevBeaconState,
8990
currentBeaconState,
90-
map[uint64]*big.Int{})
91+
map[uint64]*big.Int{},
92+
map[uint64][]*electra.PendingConsolidation{},
93+
)
9194

9295
require.NoError(t, err)
9396
require.Equal(t, indexLessBalance, []uint64{0, 2})
@@ -118,7 +121,8 @@ func Test_GetValidatorsWithLessBalance_NonConsecutive(t *testing.T) {
118121
[]uint64{},
119122
prevBeaconState,
120123
currentBeaconState,
121-
map[uint64]*big.Int{})
124+
map[uint64]*big.Int{},
125+
map[uint64][]*electra.PendingConsolidation{})
122126

123127
require.Error(t, err)
124128
}
@@ -252,3 +256,52 @@ func Test_IsBitSet(t *testing.T) {
252256
is = isBitSet(5, 2)
253257
require.Equal(t, true, is)
254258
}
259+
260+
func Test_GetProcessedConsolidations(t *testing.T) {
261+
prevBeaconState := &spec.VersionedBeaconState{
262+
Electra: &electra.BeaconState{
263+
PendingConsolidations: []*electra.PendingConsolidation{
264+
{SourceIndex: 0, TargetIndex: 1},
265+
{SourceIndex: 2, TargetIndex: 1},
266+
},
267+
Validators: []*phase0.Validator{
268+
{Slashed: false},
269+
{Slashed: false},
270+
{Slashed: false},
271+
},
272+
},
273+
}
274+
currentBeaconState := &spec.VersionedBeaconState{
275+
Electra: &electra.BeaconState{
276+
PendingConsolidations: []*electra.PendingConsolidation{},
277+
Validators: []*phase0.Validator{
278+
{Slashed: false},
279+
{Slashed: false},
280+
{Slashed: true},
281+
},
282+
},
283+
}
284+
processedConsolidations, err := GetProcessedConsolidations(prevBeaconState, currentBeaconState)
285+
require.NoError(t, err)
286+
287+
require.Equal(t, len(processedConsolidations), 1)
288+
require.Equal(t, len(processedConsolidations[1]), 1)
289+
require.Equal(t, processedConsolidations[1][0].SourceIndex, phase0.ValidatorIndex(0))
290+
require.Equal(t, processedConsolidations[1][0].TargetIndex, phase0.ValidatorIndex(1))
291+
}
292+
293+
func Test_GetProcessedConsolidations_NilPendingConsolidations(t *testing.T) {
294+
prevBeaconState := &spec.VersionedBeaconState{
295+
Electra: &electra.BeaconState{
296+
PendingConsolidations: nil,
297+
},
298+
}
299+
currentBeaconState := &spec.VersionedBeaconState{
300+
Electra: &electra.BeaconState{
301+
PendingConsolidations: nil,
302+
},
303+
}
304+
processedConsolidations, err := GetProcessedConsolidations(prevBeaconState, currentBeaconState)
305+
require.Error(t, err)
306+
require.Nil(t, processedConsolidations)
307+
}

metrics/metrics.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,11 @@ func (a *Metrics) ProcessEpoch(
358358
// Map to quickly convert public keys to index
359359
valKeyToIndex := PopulateKeysToIndexesMap(currentBeaconState)
360360

361+
processedConsolidations, err := GetProcessedConsolidations(prevBeaconState, currentBeaconState)
362+
if err != nil {
363+
return nil, errors.Wrap(err, "error getting processed consolidations")
364+
}
365+
361366
relayRewardsPerPool, slotsWithMEVRewards, err := a.relayRewards.GetRelayRewards(currentEpoch)
362367
if err != nil {
363368
return nil, errors.Wrap(err, "error getting relay rewards")
@@ -384,7 +389,17 @@ func (a *Metrics) ProcessEpoch(
384389
if reward, ok := relayRewardsPerPool[poolName]; ok {
385390
relayRewards.Add(relayRewards, reward)
386391
}
387-
err = a.beaconState.Run(pubKeys, poolName, currentBeaconState, prevBeaconState, valKeyToIndex, relayRewards, validatorIndexToWithdrawalAmount, proposerTips)
392+
err = a.beaconState.Run(
393+
pubKeys,
394+
poolName,
395+
currentBeaconState,
396+
prevBeaconState,
397+
valKeyToIndex,
398+
relayRewards,
399+
validatorIndexToWithdrawalAmount,
400+
proposerTips,
401+
processedConsolidations,
402+
)
388403
if err != nil {
389404
return nil, errors.Wrap(err, "error running beacon state")
390405
}

0 commit comments

Comments
 (0)