Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Electra: BeaconState implementation #13919

Merged
merged 21 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9e6431c
Electra: Beacon State
prestonvanloon Apr 26, 2024
178642e
Electra: Beacon state fixes from PR 13919
prestonvanloon Apr 26, 2024
3e6afd6
Add missing tests - part 1
prestonvanloon May 1, 2024
514fd29
Split eip_7251_root.go into different files and reuse/share code with…
prestonvanloon May 1, 2024
a2765ce
Add missing tests - part 2
prestonvanloon May 1, 2024
4272074
deposit receipts start index getters and setters (#13947)
james-prysm May 2, 2024
8c8d9d3
Add missing tests - part 3 of 3
prestonvanloon May 2, 2024
be3a999
add tests for beacon-chain/state/state-native/getters_balance_deposit…
prestonvanloon May 2, 2024
45a914f
Add electra field to testing/util/block.go execution payload
prestonvanloon May 2, 2024
f542639
godoc commentary on public methods
prestonvanloon May 2, 2024
1339d2d
Fix failing test
prestonvanloon May 2, 2024
49d5b88
Add balances index out of bounds check and relevant tests.
prestonvanloon May 3, 2024
3b961ec
Revert switch case electra
prestonvanloon May 3, 2024
6b4e4a9
Instead of copying spectest data into testdata, use the spectest depe…
prestonvanloon May 3, 2024
c6d6bfc
Deepsource fixes
prestonvanloon May 3, 2024
41a6263
Address @rkapka PR feedback
prestonvanloon May 3, 2024
b8a29ef
s/MaxPendingPartialsPerWithdrawalSweep/MaxPendingPartialsPerWithdrawa…
prestonvanloon May 3, 2024
2bfac80
Use multivalue slice compatible accessors for validator and balance i…
prestonvanloon May 3, 2024
0258b67
More @rkapka feedback. What a great reviewer!
prestonvanloon May 3, 2024
67dd466
More tests for branching logic in ExitEpochAndUpdateChurn
prestonvanloon May 3, 2024
4ff0357
fix build
prestonvanloon May 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions beacon-chain/blockchain/execution_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
var attr payloadattribute.Attributer
switch st.Version() {
case version.Deneb:
withdrawals, err := st.ExpectedWithdrawals()
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
return emptyAttri
Expand All @@ -342,7 +342,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
return emptyAttri
}
case version.Capella:
withdrawals, err := st.ExpectedWithdrawals()
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
return emptyAttri
Expand Down
2 changes: 0 additions & 2 deletions beacon-chain/core/blocks/exit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,6 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
}

func TestVerifyExitAndSignature(t *testing.T) {
undo := util.HackDenebMaxuint(t)
defer undo()
Comment on lines -138 to -139
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was renamed to HackElectraMaxuint and serves the same purpose. It's no longer needed in this particular test.

denebSlot, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
require.NoError(t, err)
tests := []struct {
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/core/blocks/withdrawals.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func ValidateBLSToExecutionChange(st state.ReadOnlyBeaconState, signed *ethpb.Si
// next_validator_index = ValidatorIndex(next_index % len(state.validators))
// state.next_withdrawal_validator_index = next_validator_index
func ProcessWithdrawals(st state.BeaconState, executionData interfaces.ExecutionData) (state.BeaconState, error) {
expectedWithdrawals, err := st.ExpectedWithdrawals()
expectedWithdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
return nil, errors.Wrap(err, "could not get expected withdrawals")
}
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/core/helpers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ go_test(
"//container/slice:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",
"//math:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
Expand Down
15 changes: 8 additions & 7 deletions beacon-chain/core/helpers/validator_churn.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package helpers

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

// BalanceChurnLimit for the current active balance, in gwei.
Expand All @@ -18,12 +19,12 @@ import (
// get_total_active_balance(state) // CHURN_LIMIT_QUOTIENT
// )
// return churn - churn % EFFECTIVE_BALANCE_INCREMENT
func BalanceChurnLimit(activeBalanceGwei uint64) uint64 {
func BalanceChurnLimit(activeBalance math.Gwei) math.Gwei {
churn := max(
params.BeaconConfig().MinPerEpochChurnLimitElectra,
(activeBalanceGwei / params.BeaconConfig().ChurnLimitQuotient),
(uint64(activeBalance) / params.BeaconConfig().ChurnLimitQuotient),
)
return churn - churn%params.BeaconConfig().EffectiveBalanceIncrement
return math.Gwei(churn - churn%params.BeaconConfig().EffectiveBalanceIncrement)
}

// ActivationExitChurnLimit for the current active balance, in gwei.
Expand All @@ -36,8 +37,8 @@ func BalanceChurnLimit(activeBalanceGwei uint64) uint64 {
// 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))
func ActivationExitChurnLimit(activeBalance math.Gwei) math.Gwei {
return min(math.Gwei(params.BeaconConfig().MaxPerEpochActivationExitChurnLimit), BalanceChurnLimit(activeBalance))
}

// ConsolidationChurnLimit for the current active balance, in gwei.
Expand All @@ -47,6 +48,6 @@ func ActivationExitChurnLimit(activeBalanceGwei uint64) uint64 {
//
// 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)
func ConsolidationChurnLimit(activeBalance math.Gwei) math.Gwei {
return BalanceChurnLimit(activeBalance) - ActivationExitChurnLimit(activeBalance)
}
27 changes: 14 additions & 13 deletions beacon-chain/core/helpers/validator_churn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,30 @@ import (

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

func TestBalanceChurnLimit(t *testing.T) {
tests := []struct {
name string
activeBalance uint64
expected uint64
activeBalance math.Gwei
expected math.Gwei
}{
{
name: "less than MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA",
activeBalance: 111,
expected: params.BeaconConfig().MinPerEpochChurnLimitElectra,
expected: math.Gwei(params.BeaconConfig().MinPerEpochChurnLimitElectra),
},
{
name: "modulo EFFECTIVE_BALANCE_INCREMENT",
activeBalance: 111 + params.BeaconConfig().MinPerEpochChurnLimitElectra*params.BeaconConfig().ChurnLimitQuotient,
expected: params.BeaconConfig().MinPerEpochChurnLimitElectra,
activeBalance: math.Gwei(111 + params.BeaconConfig().MinPerEpochChurnLimitElectra*params.BeaconConfig().ChurnLimitQuotient),
expected: math.Gwei(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,
activeBalance: math.Gwei(2000 * params.BeaconConfig().EffectiveBalanceIncrement * params.BeaconConfig().ChurnLimitQuotient),
expected: math.Gwei(2000 * params.BeaconConfig().EffectiveBalanceIncrement),
},
}

Expand All @@ -41,18 +42,18 @@ func TestBalanceChurnLimit(t *testing.T) {
func TestActivationExitChurnLimit(t *testing.T) {
tests := []struct {
name string
activeBalance uint64
expected uint64
activeBalance math.Gwei
expected math.Gwei
}{
{
name: "less than MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT",
activeBalance: 1,
expected: params.BeaconConfig().MinPerEpochChurnLimitElectra,
expected: math.Gwei(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,
activeBalance: math.Gwei(2000 * params.BeaconConfig().EffectiveBalanceIncrement * params.BeaconConfig().ChurnLimitQuotient),
expected: math.Gwei(params.BeaconConfig().MaxPerEpochActivationExitChurnLimit),
},
}

Expand All @@ -66,6 +67,6 @@ func TestActivationExitChurnLimit(t *testing.T) {
// FuzzConsolidationChurnLimit exercises BalanceChurnLimit and ActivationExitChurnLimit
func FuzzConsolidationChurnLimit(f *testing.F) {
f.Fuzz(func(t *testing.T, activeBalance uint64) {
helpers.ConsolidationChurnLimit(activeBalance)
helpers.ConsolidationChurnLimit(math.Gwei(activeBalance))
})
}
2 changes: 1 addition & 1 deletion beacon-chain/rpc/eth/builder/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (s *Server) ExpectedWithdrawals(w http.ResponseWriter, r *http.Request) {
})
return
}
withdrawals, err := st.ExpectedWithdrawals()
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
httputil.WriteError(w, &httputil.DefaultJsonError{
Message: "could not get expected withdrawals",
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/rpc/eth/config/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func TestGetSpec(t *testing.T) {
config.PendingPartialWithdrawalsLimit = 80
config.MinActivationBalance = 81
config.PendingBalanceDepositLimit = 82
config.MaxPendingPartialsPerWithdrawalSweep = 83
config.MaxPendingPartialsPerWithdrawalsSweep = 83
config.PendingConsolidationsLimit = 84
config.MaxPartialWithdrawalsPerPayload = 85
config.FullExitRequestAmount = 86
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/rpc/eth/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWrite
SuggestedFeeRecipient: hexutil.Encode(headPayload.FeeRecipient()),
}
case version.Capella:
withdrawals, err := headState.ExpectedWithdrawals()
withdrawals, _, err := headState.ExpectedWithdrawals()
if err != nil {
return write(w, flusher, "Could not get head state expected withdrawals: "+err.Error())
}
Expand All @@ -460,7 +460,7 @@ func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWrite
Withdrawals: structs.WithdrawalsFromConsensus(withdrawals),
}
case version.Deneb:
withdrawals, err := headState.ExpectedWithdrawals()
withdrawals, _, err := headState.ExpectedWithdrawals()
if err != nil {
return write(w, flusher, "Could not get head state expected withdrawals: "+err.Error())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe
var attr payloadattribute.Attributer
switch st.Version() {
case version.Deneb:
withdrawals, err := st.ExpectedWithdrawals()
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
return nil, false, err
}
Expand All @@ -143,7 +143,7 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe
return nil, false, err
}
case version.Capella:
withdrawals, err := st.ExpectedWithdrawals()
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
return nil, false, err
}
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/state/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ go_library(
"//config/fieldparams:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
Expand Down
48 changes: 45 additions & 3 deletions beacon-chain/state/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/math"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
)
Expand Down Expand Up @@ -56,6 +57,8 @@ type ReadOnlyBeaconState interface {
ReadOnlyParticipation
ReadOnlyInactivity
ReadOnlySyncCommittee
ReadOnlyDeposits
ReadOnlyConsolidations
ToProtoUnsafe() interface{}
ToProto() interface{}
GenesisTime() uint64
Expand Down Expand Up @@ -87,6 +90,9 @@ type WriteOnlyBeaconState interface {
WriteOnlyParticipation
WriteOnlyInactivity
WriteOnlySyncCommittee
WriteOnlyConsolidations
WriteOnlyWithdrawals
WriteOnlyDeposits
SetGenesisTime(val uint64) error
SetGenesisValidatorsRoot(val []byte) error
SetSlot(val primitives.Slot) error
Expand All @@ -98,8 +104,6 @@ type WriteOnlyBeaconState interface {
AppendHistoricalRoots(root [32]byte) error
AppendHistoricalSummaries(*ethpb.HistoricalSummary) error
SetLatestExecutionPayloadHeader(payload interfaces.ExecutionData) error
SetNextWithdrawalIndex(i uint64) error
SetNextWithdrawalValidatorIndex(i primitives.ValidatorIndex) error
SaveValidatorIndices()
}

Expand Down Expand Up @@ -134,6 +138,7 @@ type ReadOnlyBalances interface {
Balances() []uint64
BalanceAtIndex(idx primitives.ValidatorIndex) (uint64, error)
BalancesLength() int
ActiveBalanceAtIndex(idx primitives.ValidatorIndex) (uint64, error)
}

// ReadOnlyCheckpoint defines a struct which only has read access to checkpoint methods.
Expand Down Expand Up @@ -182,9 +187,11 @@ type ReadOnlyAttestations interface {

// ReadOnlyWithdrawals defines a struct which only has read access to withdrawal methods.
type ReadOnlyWithdrawals interface {
ExpectedWithdrawals() ([]*enginev1.Withdrawal, error)
ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, error)
NextWithdrawalValidatorIndex() (primitives.ValidatorIndex, error)
NextWithdrawalIndex() (uint64, error)
PendingBalanceToWithdraw(idx primitives.ValidatorIndex) (uint64, error)
NumPendingPartialWithdrawals() (uint64, error)
}

// ReadOnlyParticipation defines a struct which only has read access to participation methods.
Expand All @@ -204,6 +211,19 @@ type ReadOnlySyncCommittee interface {
NextSyncCommittee() (*ethpb.SyncCommittee, error)
}

type ReadOnlyDeposits interface {
DepositBalanceToConsume() (math.Gwei, error)
DepositReceiptsStartIndex() (uint64, error)
PendingBalanceDeposits() ([]*ethpb.PendingBalanceDeposit, error)
}

type ReadOnlyConsolidations interface {
ConsolidationBalanceToConsume() (math.Gwei, error)
EarliestConsolidationEpoch() (primitives.Epoch, error)
PendingConsolidations() ([]*ethpb.PendingConsolidation, error)
NumPendingConsolidations() (uint64, error)
}

// WriteOnlyBlockRoots defines a struct which only has write access to block roots methods.
type WriteOnlyBlockRoots interface {
SetBlockRoots(val [][]byte) error
Expand All @@ -222,6 +242,7 @@ type WriteOnlyEth1Data interface {
SetEth1DataVotes(val []*ethpb.Eth1Data) error
AppendEth1DataVotes(val *ethpb.Eth1Data) error
SetEth1DepositIndex(val uint64) error
ExitEpochAndUpdateChurn(exitBalance math.Gwei) (primitives.Epoch, error)
}

// WriteOnlyValidators defines a struct which only has write access to validators methods.
Expand Down Expand Up @@ -283,3 +304,24 @@ type WriteOnlySyncCommittee interface {
SetCurrentSyncCommittee(val *ethpb.SyncCommittee) error
SetNextSyncCommittee(val *ethpb.SyncCommittee) error
}

type WriteOnlyWithdrawals interface {
AppendPendingPartialWithdrawal(ppw *ethpb.PendingPartialWithdrawal) error
DequeuePartialWithdrawals(num uint64) error
SetNextWithdrawalIndex(i uint64) error
SetNextWithdrawalValidatorIndex(i primitives.ValidatorIndex) error
}

type WriteOnlyConsolidations interface {
AppendPendingConsolidation(val *ethpb.PendingConsolidation) error
SetConsolidationBalanceToConsume(math.Gwei) error
SetEarliestConsolidationEpoch(epoch primitives.Epoch) error
SetPendingConsolidations(val []*ethpb.PendingConsolidation) error
}

type WriteOnlyDeposits interface {
AppendPendingBalanceDeposit(index primitives.ValidatorIndex, amount uint64) error
SetDepositReceiptsStartIndex(index uint64) error
SetPendingBalanceDeposits(val []*ethpb.PendingBalanceDeposit) error
SetDepositBalanceToConsume(math.Gwei) error
}
Loading
Loading