Skip to content

Commit

Permalink
Electra: beacon-chain/core/helpers (#13921)
Browse files Browse the repository at this point in the history
* Electra helpers

* Electra helper tests and other fixes

* @terencechain feedback
  • Loading branch information
prestonvanloon authored Apr 26, 2024
1 parent bf5e667 commit 8df62a5
Show file tree
Hide file tree
Showing 7 changed files with 663 additions and 24 deletions.
21 changes: 21 additions & 0 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion beacon-chain/core/epoch/epoch_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func ProcessRegistryUpdates(ctx context.Context, state state.BeaconState) (state
activationEligibilityEpoch := time.CurrentEpoch(state) + 1
for idx, validator := range vals {
// Process the validators for activation eligibility.
if helpers.IsEligibleForActivationQueue(validator) {
if helpers.IsEligibleForActivationQueue(validator, currentEpoch) {
validator.ActivationEligibilityEpoch = activationEligibilityEpoch
if err := state.UpdateValidatorAtIndex(primitives.ValidatorIndex(idx), validator); err != nil {
return nil, err
Expand Down
2 changes: 2 additions & 0 deletions beacon-chain/core/helpers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ go_library(
"rewards_penalties.go",
"shuffle.go",
"sync_committee.go",
"validator_churn.go",
"validators.go",
"weak_subjectivity.go",
],
Expand Down Expand Up @@ -56,6 +57,7 @@ go_test(
"rewards_penalties_test.go",
"shuffle_test.go",
"sync_committee_test.go",
"validator_churn_test.go",
"validators_test.go",
"weak_subjectivity_test.go",
],
Expand Down
52 changes: 52 additions & 0 deletions beacon-chain/core/helpers/validator_churn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package helpers

import (
"github.com/prysmaticlabs/prysm/v5/config/params"
)

// BalanceChurnLimit for the current active balance, in gwei.
// New in Electra EIP-7251: https://eips.ethereum.org/EIPS/eip-7251
//
// Spec definition:
//
// def get_balance_churn_limit(state: BeaconState) -> Gwei:
// """
// Return the churn limit for the current epoch.
// """
// churn = max(
// MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA,
// get_total_active_balance(state) // CHURN_LIMIT_QUOTIENT
// )
// return churn - churn % EFFECTIVE_BALANCE_INCREMENT
func BalanceChurnLimit(activeBalanceGwei uint64) uint64 {
churn := max(
params.BeaconConfig().MinPerEpochChurnLimitElectra,
(activeBalanceGwei / params.BeaconConfig().ChurnLimitQuotient),
)
return churn - churn%params.BeaconConfig().EffectiveBalanceIncrement
}

// ActivationExitChurnLimit for the current active balance, in gwei.
// New in Electra EIP-7251: https://eips.ethereum.org/EIPS/eip-7251
//
// Spec definition:
//
// def get_activation_exit_churn_limit(state: BeaconState) -> Gwei:
// """
// Return the churn limit for the current epoch dedicated to activations and exits.
// """
// return min(MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT, get_balance_churn_limit(state))
func ActivationExitChurnLimit(activeBalanceGwei uint64) uint64 {
return min(params.BeaconConfig().MaxPerEpochActivationExitChurnLimit, BalanceChurnLimit(activeBalanceGwei))
}

// ConsolidationChurnLimit for the current active balance, in gwei.
// New in EIP-7251: https://eips.ethereum.org/EIPS/eip-7251
//
// Spec definition:
//
// def get_consolidation_churn_limit(state: BeaconState) -> Gwei:
// return get_balance_churn_limit(state) - get_activation_exit_churn_limit(state)
func ConsolidationChurnLimit(activeBalanceGwei uint64) uint64 {
return BalanceChurnLimit(activeBalanceGwei) - ActivationExitChurnLimit(activeBalanceGwei)
}
71 changes: 71 additions & 0 deletions beacon-chain/core/helpers/validator_churn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package helpers_test

import (
"testing"

"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
)

func TestBalanceChurnLimit(t *testing.T) {
tests := []struct {
name string
activeBalance uint64
expected uint64
}{
{
name: "less than MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA",
activeBalance: 111,
expected: params.BeaconConfig().MinPerEpochChurnLimitElectra,
},
{
name: "modulo EFFECTIVE_BALANCE_INCREMENT",
activeBalance: 111 + params.BeaconConfig().MinPerEpochChurnLimitElectra*params.BeaconConfig().ChurnLimitQuotient,
expected: params.BeaconConfig().MinPerEpochChurnLimitElectra,
},
{
name: "more than MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA",
activeBalance: 2000 * params.BeaconConfig().EffectiveBalanceIncrement * params.BeaconConfig().ChurnLimitQuotient,
expected: 2000 * params.BeaconConfig().EffectiveBalanceIncrement,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, helpers.BalanceChurnLimit(tt.activeBalance))
})
}
}

func TestActivationExitChurnLimit(t *testing.T) {
tests := []struct {
name string
activeBalance uint64
expected uint64
}{
{
name: "less than MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT",
activeBalance: 1,
expected: params.BeaconConfig().MinPerEpochChurnLimitElectra,
},
{
name: "more than MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT",
activeBalance: 2000 * params.BeaconConfig().EffectiveBalanceIncrement * params.BeaconConfig().ChurnLimitQuotient,
expected: params.BeaconConfig().MaxPerEpochActivationExitChurnLimit,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, helpers.ActivationExitChurnLimit(tt.activeBalance))
})
}
}

// FuzzConsolidationChurnLimit exercises BalanceChurnLimit and ActivationExitChurnLimit
func FuzzConsolidationChurnLimit(f *testing.F) {
f.Fuzz(func(t *testing.T, activeBalance uint64) {
helpers.ConsolidationChurnLimit(activeBalance)
})
}
Loading

0 comments on commit 8df62a5

Please sign in to comment.