mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
Electra: BeaconState implementation (#13919)
* Electra: Beacon State * Electra: Beacon state fixes from PR 13919 * Add missing tests - part 1 * Split eip_7251_root.go into different files and reuse/share code with historical state summaries root. It's identical! * Add missing tests - part 2 * deposit receipts start index getters and setters (#13947) * adding in getters and setters for deposit receipts start index * adding tests * gaz * Add missing tests - part 3 of 3 Update the electra withdrawal example with a ssz state containing pending partial withdrawals * add tests for beacon-chain/state/state-native/getters_balance_deposits.go * Add electra field to testing/util/block.go execution payload * godoc commentary on public methods * Fix failing test * Add balances index out of bounds check and relevant tests. * Revert switch case electra * Instead of copying spectest data into testdata, use the spectest dependency * Deepsource fixes * Address @rkapka PR feedback * s/MaxPendingPartialsPerWithdrawalSweep/MaxPendingPartialsPerWithdrawalsSweep/ * Use multivalue slice compatible accessors for validator and balance in ActiveBalanceAtIndex * More @rkapka feedback. What a great reviewer! * More tests for branching logic in ExitEpochAndUpdateChurn * fix build --------- Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -135,8 +135,6 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyExitAndSignature(t *testing.T) {
|
||||
undo := util.HackDenebMaxuint(t)
|
||||
defer undo()
|
||||
denebSlot, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
@@ -56,6 +57,8 @@ type ReadOnlyBeaconState interface {
|
||||
ReadOnlyParticipation
|
||||
ReadOnlyInactivity
|
||||
ReadOnlySyncCommittee
|
||||
ReadOnlyDeposits
|
||||
ReadOnlyConsolidations
|
||||
ToProtoUnsafe() interface{}
|
||||
ToProto() interface{}
|
||||
GenesisTime() uint64
|
||||
@@ -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
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -3,11 +3,16 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"beacon_state_mainnet.go",
|
||||
"beacon_state_minimal.go", # keep
|
||||
"doc.go",
|
||||
"error.go",
|
||||
"getters_attestation.go",
|
||||
"getters_balance_deposits.go",
|
||||
"getters_block.go",
|
||||
"getters_checkpoint.go",
|
||||
"getters_consolidation.go",
|
||||
"getters_deposit_receipts.go",
|
||||
"getters_eth1.go",
|
||||
"getters_misc.go",
|
||||
"getters_participation.go",
|
||||
@@ -22,8 +27,12 @@ go_library(
|
||||
"proofs.go",
|
||||
"readonly_validator.go",
|
||||
"setters_attestation.go",
|
||||
"setters_balance_deposits.go",
|
||||
"setters_block.go",
|
||||
"setters_checkpoint.go",
|
||||
"setters_churn.go",
|
||||
"setters_consolidation.go",
|
||||
"setters_deposit_receipts.go",
|
||||
"setters_eth1.go",
|
||||
"setters_misc.go",
|
||||
"setters_participation.go",
|
||||
@@ -38,13 +47,11 @@ go_library(
|
||||
"state_trie.go",
|
||||
"types.go",
|
||||
"validator_index_cache.go",
|
||||
] + select({
|
||||
"//config:mainnet": ["beacon_state_mainnet.go"],
|
||||
"//config:minimal": ["beacon_state_minimal.go"],
|
||||
}),
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/time:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/fieldtrie:go_default_library",
|
||||
@@ -82,8 +89,11 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"getters_attestation_test.go",
|
||||
"getters_balance_deposits_test.go",
|
||||
"getters_block_test.go",
|
||||
"getters_checkpoint_test.go",
|
||||
"getters_consolidation_test.go",
|
||||
"getters_deposit_receipts_test.go",
|
||||
"getters_participation_test.go",
|
||||
"getters_test.go",
|
||||
"getters_validator_test.go",
|
||||
@@ -94,9 +104,14 @@ go_test(
|
||||
"readonly_validator_test.go",
|
||||
"references_test.go",
|
||||
"setters_attestation_test.go",
|
||||
"setters_balance_deposits_test.go",
|
||||
"setters_churn_test.go",
|
||||
"setters_consolidation_test.go",
|
||||
"setters_deposit_receipts_test.go",
|
||||
"setters_eth1_test.go",
|
||||
"setters_misc_test.go",
|
||||
"setters_participation_test.go",
|
||||
"setters_payload_header_test.go",
|
||||
"setters_validator_test.go",
|
||||
"setters_withdrawal_test.go",
|
||||
"state_fuzz_test.go",
|
||||
@@ -105,9 +120,12 @@ go_test(
|
||||
"types_test.go",
|
||||
"validator_index_cache_test.go",
|
||||
],
|
||||
data = glob(["testdata/**"]),
|
||||
data = glob(["testdata/**"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native/types:go_default_library",
|
||||
@@ -116,11 +134,14 @@ go_test(
|
||||
"//config/features:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
"//crypto/rand:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/interop:go_default_library",
|
||||
@@ -128,9 +149,13 @@ go_test(
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_snappy//:go_default_library",
|
||||
"@com_github_google_go_cmp//cmp:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_protobuf//testing/protocmp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
"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"
|
||||
)
|
||||
@@ -57,9 +58,21 @@ type BeaconState struct {
|
||||
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader
|
||||
latestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella
|
||||
latestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb
|
||||
latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra
|
||||
nextWithdrawalIndex uint64
|
||||
nextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||
|
||||
// Electra fields
|
||||
depositReceiptsStartIndex uint64
|
||||
depositBalanceToConsume math.Gwei
|
||||
exitBalanceToConsume math.Gwei
|
||||
earliestExitEpoch primitives.Epoch
|
||||
consolidationBalanceToConsume math.Gwei
|
||||
earliestConsolidationEpoch primitives.Epoch
|
||||
pendingBalanceDeposits []*ethpb.PendingBalanceDeposit // pending_balance_deposits: List[PendingBalanceDeposit, PENDING_BALANCE_DEPOSITS_LIMIT]
|
||||
pendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal // pending_partial_withdrawals: List[PartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT]
|
||||
pendingConsolidations []*ethpb.PendingConsolidation // pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT]
|
||||
|
||||
id uint64
|
||||
lock sync.RWMutex
|
||||
dirtyFields map[types.FieldIndex]bool
|
||||
@@ -103,8 +116,19 @@ type beaconStateMarshalable struct {
|
||||
NextSyncCommittee *ethpb.SyncCommittee `json:"next_sync_committee" yaml:"next_sync_committee"`
|
||||
LatestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader `json:"latest_execution_payload_header" yaml:"latest_execution_payload_header"`
|
||||
LatestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella `json:"latest_execution_payload_header_capella" yaml:"latest_execution_payload_header_capella"`
|
||||
LatestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb `json:"latest_execution_payload_header_deneb" yaml:"latest_execution_payload_header_deneb"`
|
||||
LatestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra `json:"latest_execution_payload_header_electra" yaml:"latest_execution_payload_header_electra"`
|
||||
NextWithdrawalIndex uint64 `json:"next_withdrawal_index" yaml:"next_withdrawal_index"`
|
||||
NextWithdrawalValidatorIndex primitives.ValidatorIndex `json:"next_withdrawal_validator_index" yaml:"next_withdrawal_validator_index"`
|
||||
DepositReceiptsStartIndex uint64 `json:"deposit_receipts_start_index" yaml:"deposit_receipts_start_index"`
|
||||
DepositBalanceToConsume math.Gwei `json:"deposit_balance_to_consume" yaml:"deposit_balance_to_consume"`
|
||||
ExitBalanceToConsume math.Gwei `json:"exit_balance_to_consume" yaml:"exit_balance_to_consume"`
|
||||
EarliestExitEpoch primitives.Epoch `json:"earliest_exit_epoch" yaml:"earliest_exit_epoch"`
|
||||
ConsolidationBalanceToConsume math.Gwei `json:"consolidation_balance_to_consume" yaml:"consolidation_balance_to_consume"`
|
||||
EarliestConsolidationEpoch primitives.Epoch `json:"earliest_consolidation_epoch" yaml:"earliest_consolidation_epoch"`
|
||||
PendingBalanceDeposits []*ethpb.PendingBalanceDeposit `json:"pending_balance_deposits" yaml:"pending_balance_deposits"`
|
||||
PendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal `json:"pending_partial_withdrawals" yaml:"pending_partial_withdrawals"`
|
||||
PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"`
|
||||
}
|
||||
|
||||
func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
@@ -162,8 +186,19 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,
|
||||
LatestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella,
|
||||
LatestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb,
|
||||
LatestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectra,
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
ConsolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
EarliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
PendingBalanceDeposits: b.pendingBalanceDeposits,
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawals,
|
||||
PendingConsolidations: b.pendingConsolidations,
|
||||
}
|
||||
return json.Marshal(marshalable)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
"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"
|
||||
)
|
||||
@@ -57,9 +58,21 @@ type BeaconState struct {
|
||||
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader
|
||||
latestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella
|
||||
latestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb
|
||||
latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra
|
||||
nextWithdrawalIndex uint64
|
||||
nextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||
|
||||
// Electra fields
|
||||
depositReceiptsStartIndex uint64
|
||||
depositBalanceToConsume math.Gwei
|
||||
exitBalanceToConsume math.Gwei
|
||||
earliestExitEpoch primitives.Epoch
|
||||
consolidationBalanceToConsume math.Gwei
|
||||
earliestConsolidationEpoch primitives.Epoch
|
||||
pendingBalanceDeposits []*ethpb.PendingBalanceDeposit // pending_balance_deposits: List[PendingBalanceDeposit, PENDING_BALANCE_DEPOSITS_LIMIT]
|
||||
pendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal // pending_partial_withdrawals: List[PartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT]
|
||||
pendingConsolidations []*ethpb.PendingConsolidation // pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT]
|
||||
|
||||
id uint64
|
||||
lock sync.RWMutex
|
||||
dirtyFields map[types.FieldIndex]bool
|
||||
@@ -103,8 +116,19 @@ type beaconStateMarshalable struct {
|
||||
NextSyncCommittee *ethpb.SyncCommittee `json:"next_sync_committee" yaml:"next_sync_committee"`
|
||||
LatestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader `json:"latest_execution_payload_header" yaml:"latest_execution_payload_header"`
|
||||
LatestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella `json:"latest_execution_payload_header_capella" yaml:"latest_execution_payload_header_capella"`
|
||||
LatestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb `json:"latest_execution_payload_header_deneb" yaml:"latest_execution_payload_header_deneb"`
|
||||
LatestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra `json:"latest_execution_payload_header_electra" yaml:"latest_execution_payload_header_electra"`
|
||||
NextWithdrawalIndex uint64 `json:"next_withdrawal_index" yaml:"next_withdrawal_index"`
|
||||
NextWithdrawalValidatorIndex primitives.ValidatorIndex `json:"next_withdrawal_validator_index" yaml:"next_withdrawal_validator_index"`
|
||||
DepositReceiptsStartIndex uint64 `json:"deposit_receipts_start_index" yaml:"deposit_receipts_start_index"`
|
||||
DepositBalanceToConsume math.Gwei `json:"deposit_balance_to_consume" yaml:"deposit_balance_to_consume"`
|
||||
ExitBalanceToConsume math.Gwei `json:"exit_balance_to_consume" yaml:"exit_balance_to_consume"`
|
||||
EarliestExitEpoch primitives.Epoch `json:"earliest_exit_epoch" yaml:"earliest_exit_epoch"`
|
||||
ConsolidationBalanceToConsume math.Gwei `json:"consolidation_balance_to_consume" yaml:"consolidation_balance_to_consume"`
|
||||
EarliestConsolidationEpoch primitives.Epoch `json:"earliest_consolidation_epoch" yaml:"earliest_consolidation_epoch"`
|
||||
PendingBalanceDeposits []*ethpb.PendingBalanceDeposit `json:"pending_balance_deposits" yaml:"pending_balance_deposits"`
|
||||
PendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal `json:"pending_partial_withdrawals" yaml:"pending_partial_withdrawals"`
|
||||
PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"`
|
||||
}
|
||||
|
||||
func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
@@ -162,8 +186,19 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,
|
||||
LatestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella,
|
||||
LatestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb,
|
||||
LatestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectra,
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
ConsolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
EarliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
PendingBalanceDeposits: b.pendingBalanceDeposits,
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawals,
|
||||
PendingConsolidations: b.pendingConsolidations,
|
||||
}
|
||||
return json.Marshal(marshalable)
|
||||
}
|
||||
|
||||
39
beacon-chain/state/state-native/getters_balance_deposits.go
Normal file
39
beacon-chain/state/state-native/getters_balance_deposits.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// DepositBalanceToConsume is a non-mutating call to the beacon state which returns the value of the
|
||||
// deposit balance to consume field. This method requires access to the RLock on the state and only
|
||||
// applies in electra or later.
|
||||
func (b *BeaconState) DepositBalanceToConsume() (math.Gwei, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("DepositBalanceToConsume", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
return b.depositBalanceToConsume, nil
|
||||
}
|
||||
|
||||
// PendingBalanceDeposits is a non-mutating call to the beacon state which returns a deep copy of
|
||||
// the pending balance deposit slice. This method requires access to the RLock on the state and
|
||||
// only applies in electra or later.
|
||||
func (b *BeaconState) PendingBalanceDeposits() ([]*ethpb.PendingBalanceDeposit, error) {
|
||||
if b.version < version.Electra {
|
||||
return nil, errNotSupported("PendingBalanceDeposits", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
return b.pendingBalanceDepositsVal(), nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) pendingBalanceDepositsVal() []*ethpb.PendingBalanceDeposit {
|
||||
if b.pendingBalanceDeposits == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ethpb.CopyPendingBalanceDeposits(b.pendingBalanceDeposits)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestDepositBalanceToConsume(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
DepositBalanceToConsume: 44,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
dbtc, err := s.DepositBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, math.Gwei(44), dbtc)
|
||||
|
||||
// Fails for older than electra state
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
_, err = s.DepositBalanceToConsume()
|
||||
require.ErrorContains(t, "not supported", err)
|
||||
}
|
||||
|
||||
func TestPendingBalanceDeposits(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
PendingBalanceDeposits: []*eth.PendingBalanceDeposit{
|
||||
{Index: 1, Amount: 2},
|
||||
{Index: 3, Amount: 4},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pbd, err := s.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, len(pbd))
|
||||
require.Equal(t, primitives.ValidatorIndex(1), pbd[0].Index)
|
||||
require.Equal(t, uint64(2), pbd[0].Amount)
|
||||
require.Equal(t, primitives.ValidatorIndex(3), pbd[1].Index)
|
||||
require.Equal(t, uint64(4), pbd[1].Amount)
|
||||
|
||||
// Fails for older than electra state
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
_, err = s.DepositBalanceToConsume()
|
||||
require.ErrorContains(t, "not supported", err)
|
||||
}
|
||||
64
beacon-chain/state/state-native/getters_consolidation.go
Normal file
64
beacon-chain/state/state-native/getters_consolidation.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// EarliestConsolidationEpoch is a non-mutating call to the beacon state which returns the value of
|
||||
// the earliest consolidation epoch field. This method requires access to the RLock on the state and
|
||||
// only applies in electra or later.
|
||||
func (b *BeaconState) EarliestConsolidationEpoch() (primitives.Epoch, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("EarliestConsolidationEpoch", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
return b.earliestConsolidationEpoch, nil
|
||||
}
|
||||
|
||||
// ConsolidationBalanceToConsume is a non-mutating call to the beacon state which returns the value
|
||||
// of the consolidation balance to consume field. This method requires access to the RLock on the
|
||||
// state and only applies in electra or later.
|
||||
func (b *BeaconState) ConsolidationBalanceToConsume() (math.Gwei, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("ConsolidationBalanceToConsume", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
return b.consolidationBalanceToConsume, nil
|
||||
}
|
||||
|
||||
// PendingConsolidations is a non-mutating call to the beacon state which returns a deep copy of the
|
||||
// pending consolidations slice. This method requires access to the RLock on the state and only
|
||||
// applies in electra or later.
|
||||
func (b *BeaconState) PendingConsolidations() ([]*ethpb.PendingConsolidation, error) {
|
||||
if b.version < version.Electra {
|
||||
return nil, errNotSupported("PendingConsolidations", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
return b.pendingConsolidationsVal(), nil
|
||||
}
|
||||
|
||||
// NumPendingConsolidations is a non-mutating call to the beacon state which returns the number of
|
||||
// pending consolidations in the beacon state. This method requires access to the RLock on the state
|
||||
// and only applies in electra or later.
|
||||
func (b *BeaconState) NumPendingConsolidations() (uint64, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("NumPendingConsolidations", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
return uint64(len(b.pendingConsolidations)), nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) pendingConsolidationsVal() []*ethpb.PendingConsolidation {
|
||||
if b.pendingConsolidations == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ethpb.CopyPendingConsolidations(b.pendingConsolidations)
|
||||
}
|
||||
118
beacon-chain/state/state-native/getters_consolidation_test.go
Normal file
118
beacon-chain/state/state-native/getters_consolidation_test.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestEarliestConsolidationEpoch(t *testing.T) {
|
||||
t.Run("electra returns expected value", func(t *testing.T) {
|
||||
want := primitives.Epoch(10)
|
||||
st, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{
|
||||
EarliestConsolidationEpoch: want,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
got, err := st.EarliestConsolidationEpoch()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
|
||||
t.Run("earlier than electra returns error", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoDeneb(ðpb.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
_, err = st.EarliestConsolidationEpoch()
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestConsolidationBalanceToConsume(t *testing.T) {
|
||||
t.Run("electra returns expected value", func(t *testing.T) {
|
||||
want := math.Gwei(10)
|
||||
st, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{
|
||||
ConsolidationBalanceToConsume: want,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
got, err := st.ConsolidationBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
|
||||
t.Run("earlier than electra returns error", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoDeneb(ðpb.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
_, err = st.ConsolidationBalanceToConsume()
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPendingConsolidations(t *testing.T) {
|
||||
t.Run("electra returns expected value", func(t *testing.T) {
|
||||
want := []*ethpb.PendingConsolidation{
|
||||
{
|
||||
SourceIndex: 1,
|
||||
TargetIndex: 2,
|
||||
},
|
||||
{
|
||||
SourceIndex: 3,
|
||||
TargetIndex: 4,
|
||||
},
|
||||
{
|
||||
SourceIndex: 5,
|
||||
TargetIndex: 6,
|
||||
},
|
||||
{
|
||||
SourceIndex: 7,
|
||||
TargetIndex: 8,
|
||||
},
|
||||
}
|
||||
st, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{
|
||||
PendingConsolidations: want,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
got, err := st.PendingConsolidations()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want, got)
|
||||
})
|
||||
|
||||
t.Run("earlier than electra returns error", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoDeneb(ðpb.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
_, err = st.PendingConsolidations()
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNumPendingConsolidations(t *testing.T) {
|
||||
t.Run("electra returns expected value", func(t *testing.T) {
|
||||
want := uint64(4)
|
||||
st, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{
|
||||
PendingConsolidations: []*ethpb.PendingConsolidation{
|
||||
{
|
||||
SourceIndex: 1,
|
||||
TargetIndex: 2,
|
||||
},
|
||||
{
|
||||
SourceIndex: 3,
|
||||
TargetIndex: 4,
|
||||
},
|
||||
{
|
||||
SourceIndex: 5,
|
||||
TargetIndex: 6,
|
||||
},
|
||||
{
|
||||
SourceIndex: 7,
|
||||
TargetIndex: 8,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
got, err := st.NumPendingConsolidations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
}
|
||||
16
beacon-chain/state/state-native/getters_deposit_receipts.go
Normal file
16
beacon-chain/state/state-native/getters_deposit_receipts.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// DepositReceiptsStartIndex is used for returning the deposit receipts start index which is used for eip6110
|
||||
func (b *BeaconState) DepositReceiptsStartIndex() (uint64, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("DepositReceiptsStartIndex", b.version)
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.depositReceiptsStartIndex, nil
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestDepositReceiptsStartIndex(t *testing.T) {
|
||||
t.Run("previous fork returns expected error", func(t *testing.T) {
|
||||
dState, _ := util.DeterministicGenesisState(t, 1)
|
||||
_, err := dState.DepositReceiptsStartIndex()
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
t.Run("electra returns expected value", func(t *testing.T) {
|
||||
want := uint64(2)
|
||||
dState, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{DepositReceiptsStartIndex: want})
|
||||
require.NoError(t, err)
|
||||
got, err := dState.DepositReceiptsStartIndex()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
@@ -19,15 +20,18 @@ func (b *BeaconState) LatestExecutionPayloadHeader() (interfaces.ExecutionData,
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
if b.version == version.Bellatrix {
|
||||
switch b.version {
|
||||
case version.Bellatrix:
|
||||
return blocks.WrappedExecutionPayloadHeader(b.latestExecutionPayloadHeaderVal())
|
||||
}
|
||||
|
||||
if b.version == version.Capella {
|
||||
case version.Capella:
|
||||
return blocks.WrappedExecutionPayloadHeaderCapella(b.latestExecutionPayloadHeaderCapellaVal(), big.NewInt(0))
|
||||
case version.Deneb:
|
||||
return blocks.WrappedExecutionPayloadHeaderDeneb(b.latestExecutionPayloadHeaderDenebVal(), big.NewInt(0))
|
||||
case version.Electra:
|
||||
return blocks.WrappedExecutionPayloadHeaderElectra(b.latestExecutionPayloadHeaderElectraVal(), big.NewInt(0))
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported version (%s) for latest execution payload header", version.String(b.version))
|
||||
}
|
||||
|
||||
return blocks.WrappedExecutionPayloadHeaderDeneb(b.latestExecutionPayloadHeaderDenebVal(), big.NewInt(0))
|
||||
}
|
||||
|
||||
// latestExecutionPayloadHeaderVal of the beacon state.
|
||||
@@ -45,3 +49,7 @@ func (b *BeaconState) latestExecutionPayloadHeaderCapellaVal() *enginev1.Executi
|
||||
func (b *BeaconState) latestExecutionPayloadHeaderDenebVal() *enginev1.ExecutionPayloadHeaderDeneb {
|
||||
return ethpb.CopyExecutionPayloadHeaderDeneb(b.latestExecutionPayloadHeaderDeneb)
|
||||
}
|
||||
|
||||
func (b *BeaconState) latestExecutionPayloadHeaderElectraVal() *enginev1.ExecutionPayloadHeaderElectra {
|
||||
return ethpb.CopyExecutionPayloadHeaderElectra(b.latestExecutionPayloadHeaderElectra)
|
||||
}
|
||||
|
||||
@@ -172,6 +172,46 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummaries,
|
||||
}
|
||||
case version.Electra:
|
||||
return ðpb.BeaconStateElectra{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.fork,
|
||||
LatestBlockHeader: b.latestBlockHeader,
|
||||
BlockRoots: br,
|
||||
StateRoots: sr,
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1Data,
|
||||
Eth1DataVotes: b.eth1DataVotes,
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: vals,
|
||||
Balances: bals,
|
||||
RandaoMixes: rm,
|
||||
Slashings: b.slashings,
|
||||
PreviousEpochParticipation: b.previousEpochParticipation,
|
||||
CurrentEpochParticipation: b.currentEpochParticipation,
|
||||
JustificationBits: b.justificationBits,
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint,
|
||||
InactivityScores: b.inactivityScoresVal(),
|
||||
CurrentSyncCommittee: b.currentSyncCommittee,
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderElectra,
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummaries,
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
ConsolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
EarliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
PendingBalanceDeposits: b.pendingBalanceDeposits,
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawals,
|
||||
PendingConsolidations: b.pendingConsolidations,
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@@ -338,6 +378,46 @@ func (b *BeaconState) ToProto() interface{} {
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummariesVal(),
|
||||
}
|
||||
case version.Electra:
|
||||
return ðpb.BeaconStateElectra{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.forkVal(),
|
||||
LatestBlockHeader: b.latestBlockHeaderVal(),
|
||||
BlockRoots: br,
|
||||
StateRoots: sr,
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1DataVal(),
|
||||
Eth1DataVotes: b.eth1DataVotesVal(),
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validatorsVal(),
|
||||
Balances: b.balancesVal(),
|
||||
RandaoMixes: rm,
|
||||
Slashings: b.slashingsVal(),
|
||||
PreviousEpochParticipation: b.previousEpochParticipationVal(),
|
||||
CurrentEpochParticipation: b.currentEpochParticipationVal(),
|
||||
JustificationBits: b.justificationBitsVal(),
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
|
||||
FinalizedCheckpoint: b.finalizedCheckpointVal(),
|
||||
InactivityScores: b.inactivityScoresVal(),
|
||||
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
|
||||
NextSyncCommittee: b.nextSyncCommitteeVal(),
|
||||
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderElectraVal(),
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummariesVal(),
|
||||
DepositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
ConsolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
EarliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
PendingBalanceDeposits: b.pendingBalanceDepositsVal(),
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawalsVal(),
|
||||
PendingConsolidations: b.pendingConsolidationsVal(),
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@@ -449,7 +529,17 @@ func ProtobufBeaconStateCapella(s interface{}) (*ethpb.BeaconStateCapella, error
|
||||
func ProtobufBeaconStateDeneb(s interface{}) (*ethpb.BeaconStateDeneb, error) {
|
||||
pbState, ok := s.(*ethpb.BeaconStateDeneb)
|
||||
if !ok {
|
||||
return nil, errors.New("input is not type pb.ProtobufBeaconStateDeneb")
|
||||
return nil, errors.New("input is not type pb.BeaconStateDeneb")
|
||||
}
|
||||
return pbState, nil
|
||||
}
|
||||
|
||||
// ProtobufBeaconStateElectra transforms an input into beacon state Electra in the form of protobuf.
|
||||
// Error is returned if the input is not type protobuf beacon state.
|
||||
func ProtobufBeaconStateElectra(s interface{}) (*ethpb.BeaconStateElectra, error) {
|
||||
pbState, ok := s.(*ethpb.BeaconStateElectra)
|
||||
if !ok {
|
||||
return nil, errors.New("input is not type pb.BeaconStateElectra")
|
||||
}
|
||||
return pbState, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package state_native
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
@@ -413,3 +414,59 @@ func (b *BeaconState) inactivityScoresVal() []uint64 {
|
||||
copy(res, b.inactivityScores)
|
||||
return res
|
||||
}
|
||||
|
||||
// ActiveBalanceAtIndex returns the active balance for the given validator.
|
||||
//
|
||||
// Spec definition:
|
||||
//
|
||||
// def get_active_balance(state: BeaconState, validator_index: ValidatorIndex) -> Gwei:
|
||||
// max_effective_balance = get_validator_max_effective_balance(state.validators[validator_index])
|
||||
// return min(state.balances[validator_index], max_effective_balance)
|
||||
func (b *BeaconState) ActiveBalanceAtIndex(i primitives.ValidatorIndex) (uint64, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("ActiveBalanceAtIndex", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
v, err := b.validatorAtIndex(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
bal, err := b.balanceAtIndex(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return min(bal, helpers.ValidatorMaxEffectiveBalance(v)), nil
|
||||
}
|
||||
|
||||
// PendingBalanceToWithdraw returns the sum of all pending withdrawals for the given validator.
|
||||
//
|
||||
// Spec definition:
|
||||
//
|
||||
// def get_pending_balance_to_withdraw(state: BeaconState, validator_index: ValidatorIndex) -> Gwei:
|
||||
// return sum(
|
||||
// withdrawal.amount for withdrawal in state.pending_partial_withdrawals if withdrawal.index == validator_index)
|
||||
func (b *BeaconState) PendingBalanceToWithdraw(idx primitives.ValidatorIndex) (uint64, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("PendingBalanceToWithdraw", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
// TODO: Consider maintaining this value in the state, if it's a potential bottleneck.
|
||||
// This is n*m complexity, but this method can only be called
|
||||
// MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD per slot. A more optimized storage indexing such as a
|
||||
// lookup map could be used to reduce the complexity marginally.
|
||||
var sum uint64
|
||||
for _, w := range b.pendingPartialWithdrawals {
|
||||
if w.Index == idx {
|
||||
sum += w.Amount
|
||||
}
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
statenative "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
testtmpl "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/testing"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
@@ -66,3 +69,79 @@ func TestValidatorIndexes(t *testing.T) {
|
||||
require.Equal(t, hexutil.Encode(readOnlyBytes[:]), hexutil.Encode(byteValue[:]))
|
||||
})
|
||||
}
|
||||
|
||||
func TestActiveBalanceAtIndex(t *testing.T) {
|
||||
// Test setup with a state with 4 validators.
|
||||
// Validators 0 & 1 have compounding withdrawal credentials while validators 2 & 3 have BLS withdrawal credentials.
|
||||
pb := ðpb.BeaconStateElectra{
|
||||
Validators: []*ethpb.Validator{
|
||||
{
|
||||
WithdrawalCredentials: []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte},
|
||||
},
|
||||
{
|
||||
WithdrawalCredentials: []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte},
|
||||
},
|
||||
{
|
||||
WithdrawalCredentials: []byte{params.BeaconConfig().BLSWithdrawalPrefixByte},
|
||||
},
|
||||
{
|
||||
WithdrawalCredentials: []byte{params.BeaconConfig().BLSWithdrawalPrefixByte},
|
||||
},
|
||||
},
|
||||
Balances: []uint64{
|
||||
55,
|
||||
math.MaxUint64,
|
||||
55,
|
||||
math.MaxUint64,
|
||||
},
|
||||
}
|
||||
state, err := statenative.InitializeFromProtoUnsafeElectra(pb)
|
||||
require.NoError(t, err)
|
||||
|
||||
ab, err := state.ActiveBalanceAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(55), ab)
|
||||
|
||||
ab, err = state.ActiveBalanceAtIndex(1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxEffectiveBalanceElectra, ab)
|
||||
|
||||
ab, err = state.ActiveBalanceAtIndex(2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(55), ab)
|
||||
|
||||
ab, err = state.ActiveBalanceAtIndex(3)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MinActivationBalance, ab)
|
||||
|
||||
// Accessing a validator index out of bounds should error.
|
||||
_, err = state.ActiveBalanceAtIndex(4)
|
||||
require.ErrorIs(t, err, consensus_types.ErrOutOfBounds)
|
||||
|
||||
// Accessing a validator wwhere balance slice is out of bounds for some reason.
|
||||
require.NoError(t, state.SetBalances([]uint64{}))
|
||||
_, err = state.ActiveBalanceAtIndex(0)
|
||||
require.ErrorIs(t, err, consensus_types.ErrOutOfBounds)
|
||||
}
|
||||
|
||||
func TestPendingBalanceToWithdraw(t *testing.T) {
|
||||
pb := ðpb.BeaconStateElectra{
|
||||
PendingPartialWithdrawals: []*ethpb.PendingPartialWithdrawal{
|
||||
{
|
||||
Amount: 100,
|
||||
},
|
||||
{
|
||||
Amount: 200,
|
||||
},
|
||||
{
|
||||
Amount: 300,
|
||||
},
|
||||
},
|
||||
}
|
||||
state, err := statenative.InitializeFromProtoUnsafeElectra(pb)
|
||||
require.NoError(t, err)
|
||||
|
||||
ab, err := state.PendingBalanceToWithdraw(0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(600), ab)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
@@ -41,10 +44,64 @@ func (b *BeaconState) NextWithdrawalValidatorIndex() (primitives.ValidatorIndex,
|
||||
|
||||
// ExpectedWithdrawals returns the withdrawals that a proposer will need to pack in the next block
|
||||
// applied to the current state. It is also used by validators to check that the execution payload carried
|
||||
// the right number of withdrawals
|
||||
func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
// the right number of withdrawals. Note: The number of partial withdrawals will be zero before EIP-7251.
|
||||
//
|
||||
// Spec definition:
|
||||
//
|
||||
// def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]:
|
||||
// epoch = get_current_epoch(state)
|
||||
// withdrawal_index = state.next_withdrawal_index
|
||||
// validator_index = state.next_withdrawal_validator_index
|
||||
// withdrawals: List[Withdrawal] = []
|
||||
//
|
||||
// # [New in Electra:EIP7251] Consume pending partial withdrawals
|
||||
// for withdrawal in state.pending_partial_withdrawals:
|
||||
// if withdrawal.withdrawable_epoch > epoch or len(withdrawals) == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP:
|
||||
// break
|
||||
//
|
||||
// validator = state.validators[withdrawal.index]
|
||||
// has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
|
||||
// has_excess_balance = state.balances[withdrawal.index] > MIN_ACTIVATION_BALANCE
|
||||
// if validator.exit_epoch == FAR_FUTURE_EPOCH and has_sufficient_effective_balance and has_excess_balance:
|
||||
// withdrawable_balance = min(state.balances[withdrawal.index] - MIN_ACTIVATION_BALANCE, withdrawal.amount)
|
||||
// withdrawals.append(Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=withdrawal.index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=withdrawable_balance,
|
||||
// ))
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
//
|
||||
// partial_withdrawals_count = len(withdrawals)
|
||||
//
|
||||
// # Sweep for remaining.
|
||||
// bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
// for _ in range(bound):
|
||||
// validator = state.validators[validator_index]
|
||||
// balance = state.balances[validator_index]
|
||||
// if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
// withdrawals.append(Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=validator_index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=balance,
|
||||
// ))
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
// elif is_partially_withdrawable_validator(validator, balance):
|
||||
// withdrawals.append(Withdrawal(
|
||||
// index=withdrawal_index,
|
||||
// validator_index=validator_index,
|
||||
// address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
// amount=balance - get_validator_max_effective_balance(validator), # [Modified in Electra:EIP7251]
|
||||
// ))
|
||||
// withdrawal_index += WithdrawalIndex(1)
|
||||
// if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
// break
|
||||
// validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
|
||||
// return withdrawals, partial_withdrawals_count
|
||||
func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, error) {
|
||||
if b.version < version.Capella {
|
||||
return nil, errNotSupported("ExpectedWithdrawals", b.version)
|
||||
return nil, 0, errNotSupported("ExpectedWithdrawals", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
@@ -55,18 +112,49 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
withdrawalIndex := b.nextWithdrawalIndex
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
|
||||
// Electra partial withdrawals functionality.
|
||||
if b.version >= version.Electra {
|
||||
for _, w := range b.pendingPartialWithdrawals {
|
||||
if w.WithdrawableEpoch > epoch || len(withdrawals) >= int(params.BeaconConfig().MaxPendingPartialsPerWithdrawalsSweep) {
|
||||
break
|
||||
}
|
||||
|
||||
v, err := b.validatorAtIndex(w.Index)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to determine withdrawals at index %d: %w", w.Index, err)
|
||||
}
|
||||
vBal, err := b.balanceAtIndex(w.Index)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("could not retrieve balance at index %d: %w", w.Index, err)
|
||||
}
|
||||
hasSufficientEffectiveBalance := v.EffectiveBalance >= params.BeaconConfig().MinActivationBalance
|
||||
hasExcessBalance := vBal > params.BeaconConfig().MinActivationBalance
|
||||
if v.ExitEpoch == params.BeaconConfig().FarFutureEpoch && hasSufficientEffectiveBalance && hasExcessBalance {
|
||||
amount := min(vBal-params.BeaconConfig().MinActivationBalance, w.Amount)
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: w.Index,
|
||||
Address: v.WithdrawalCredentials[12:],
|
||||
Amount: amount,
|
||||
})
|
||||
withdrawalIndex++
|
||||
}
|
||||
}
|
||||
}
|
||||
partialWithdrawalsCount := uint64(len(withdrawals))
|
||||
|
||||
validatorsLen := b.validatorsLen()
|
||||
bound := mathutil.Min(uint64(validatorsLen), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
|
||||
for i := uint64(0); i < bound; i++ {
|
||||
val, err := b.validatorAtIndex(validatorIndex)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not retrieve validator at index %d", validatorIndex)
|
||||
return nil, 0, errors.Wrapf(err, "could not retrieve validator at index %d", validatorIndex)
|
||||
}
|
||||
balance, err := b.balanceAtIndex(validatorIndex)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not retrieve balance at index %d", validatorIndex)
|
||||
return nil, 0, errors.Wrapf(err, "could not retrieve balance at index %d", validatorIndex)
|
||||
}
|
||||
if balance > 0 && isFullyWithdrawableValidator(val, epoch) {
|
||||
if helpers.IsFullyWithdrawableValidator(val, balance, epoch) {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
@@ -74,12 +162,12 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
Amount: balance,
|
||||
})
|
||||
withdrawalIndex++
|
||||
} else if isPartiallyWithdrawableValidator(val, balance) {
|
||||
} else if helpers.IsPartiallyWithdrawableValidator(val, balance, epoch) {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
Address: bytesutil.SafeCopyBytes(val.WithdrawalCredentials[ETH1AddressOffset:]),
|
||||
Amount: balance - params.BeaconConfig().MaxEffectiveBalance,
|
||||
Amount: balance - helpers.ValidatorMaxEffectiveBalance(val),
|
||||
})
|
||||
withdrawalIndex++
|
||||
}
|
||||
@@ -91,36 +179,17 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
validatorIndex = 0
|
||||
}
|
||||
}
|
||||
return withdrawals, nil
|
||||
|
||||
return withdrawals, partialWithdrawalsCount, nil
|
||||
}
|
||||
|
||||
// hasETH1WithdrawalCredential returns whether the validator has an ETH1
|
||||
// Withdrawal prefix. It assumes that the caller has a lock on the state
|
||||
func hasETH1WithdrawalCredential(val *ethpb.Validator) bool {
|
||||
if val == nil {
|
||||
return false
|
||||
}
|
||||
cred := val.WithdrawalCredentials
|
||||
return len(cred) > 0 && cred[0] == params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
func (b *BeaconState) pendingPartialWithdrawalsVal() []*ethpb.PendingPartialWithdrawal {
|
||||
return ethpb.CopyPendingPartialWithdrawals(b.pendingPartialWithdrawals)
|
||||
}
|
||||
|
||||
// isFullyWithdrawableValidator returns whether the validator is able to perform a full
|
||||
// withdrawal. This differ from the spec helper in that the balance > 0 is not
|
||||
// checked. This function assumes that the caller holds a lock on the state
|
||||
func isFullyWithdrawableValidator(val *ethpb.Validator, epoch primitives.Epoch) bool {
|
||||
if val == nil {
|
||||
return false
|
||||
func (b *BeaconState) NumPendingPartialWithdrawals() (uint64, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("NumPendingPartialWithdrawals", b.version)
|
||||
}
|
||||
return hasETH1WithdrawalCredential(val) && val.WithdrawableEpoch <= epoch
|
||||
}
|
||||
|
||||
// isPartiallyWithdrawable returns whether the validator is able to perform a
|
||||
// partial withdrawal. This function assumes that the caller has a lock on the state
|
||||
func isPartiallyWithdrawableValidator(val *ethpb.Validator, balance uint64) bool {
|
||||
if val == nil {
|
||||
return false
|
||||
}
|
||||
hasMaxBalance := val.EffectiveBalance == params.BeaconConfig().MaxEffectiveBalance
|
||||
hasExcessBalance := balance > params.BeaconConfig().MaxEffectiveBalance
|
||||
return hasETH1WithdrawalCredential(val) && hasExcessBalance && hasMaxBalance
|
||||
return uint64(len(b.pendingPartialWithdrawals)), nil
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package state_native
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
@@ -10,588 +12,341 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestNextWithdrawalIndex(t *testing.T) {
|
||||
t.Run("ok for deneb", func(t *testing.T) {
|
||||
s := BeaconState{version: version.Deneb, nextWithdrawalIndex: 123}
|
||||
s, err := state_native.InitializeFromProtoDeneb(ðpb.BeaconStateDeneb{NextWithdrawalIndex: 123})
|
||||
require.NoError(t, err)
|
||||
i, err := s.NextWithdrawalIndex()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(123), i)
|
||||
})
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
s := BeaconState{version: version.Capella, nextWithdrawalIndex: 123}
|
||||
s, err := state_native.InitializeFromProtoCapella(ðpb.BeaconStateCapella{NextWithdrawalIndex: 123})
|
||||
require.NoError(t, err)
|
||||
i, err := s.NextWithdrawalIndex()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(123), i)
|
||||
})
|
||||
t.Run("version before Capella not supported", func(t *testing.T) {
|
||||
s := BeaconState{version: version.Bellatrix}
|
||||
_, err := s.NextWithdrawalIndex()
|
||||
s, err := state_native.InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
require.NoError(t, err)
|
||||
_, err = s.NextWithdrawalIndex()
|
||||
assert.ErrorContains(t, "NextWithdrawalIndex is not supported", err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNextWithdrawalValidatorIndex(t *testing.T) {
|
||||
t.Run("ok for deneb", func(t *testing.T) {
|
||||
s := BeaconState{version: version.Deneb, nextWithdrawalValidatorIndex: 123}
|
||||
pb := ðpb.BeaconStateDeneb{NextWithdrawalValidatorIndex: 123}
|
||||
s, err := state_native.InitializeFromProtoDeneb(pb)
|
||||
require.NoError(t, err)
|
||||
i, err := s.NextWithdrawalValidatorIndex()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, primitives.ValidatorIndex(123), i)
|
||||
})
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
s := BeaconState{version: version.Capella, nextWithdrawalValidatorIndex: 123}
|
||||
pb := ðpb.BeaconStateCapella{NextWithdrawalValidatorIndex: 123}
|
||||
s, err := state_native.InitializeFromProtoCapella(pb)
|
||||
require.NoError(t, err)
|
||||
i, err := s.NextWithdrawalValidatorIndex()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, primitives.ValidatorIndex(123), i)
|
||||
})
|
||||
t.Run("version before Capella not supported", func(t *testing.T) {
|
||||
s := BeaconState{version: version.Bellatrix}
|
||||
_, err := s.NextWithdrawalValidatorIndex()
|
||||
s, err := state_native.InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
require.NoError(t, err)
|
||||
_, err = s.NextWithdrawalValidatorIndex()
|
||||
assert.ErrorContains(t, "NextWithdrawalValidatorIndex is not supported", err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestHasETH1WithdrawalCredentials(t *testing.T) {
|
||||
creds := []byte{0xFA, 0xCC}
|
||||
v := ðpb.Validator{WithdrawalCredentials: creds}
|
||||
require.Equal(t, false, hasETH1WithdrawalCredential(v))
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v = ðpb.Validator{WithdrawalCredentials: creds}
|
||||
require.Equal(t, true, hasETH1WithdrawalCredential(v))
|
||||
// No Withdrawal cred
|
||||
v = ðpb.Validator{}
|
||||
require.Equal(t, false, hasETH1WithdrawalCredential(v))
|
||||
}
|
||||
|
||||
func TestIsFullyWithdrawableValidator(t *testing.T) {
|
||||
// No ETH1 prefix
|
||||
creds := []byte{0xFA, 0xCC}
|
||||
v := ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
WithdrawableEpoch: 2,
|
||||
}
|
||||
require.Equal(t, false, isFullyWithdrawableValidator(v, 3))
|
||||
// Wrong withdrawable epoch
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v = ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
WithdrawableEpoch: 2,
|
||||
}
|
||||
require.Equal(t, false, isFullyWithdrawableValidator(v, 1))
|
||||
// Fully withdrawable
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v = ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
WithdrawableEpoch: 2,
|
||||
}
|
||||
require.Equal(t, true, isFullyWithdrawableValidator(v, 3))
|
||||
}
|
||||
|
||||
func TestExpectedWithdrawals(t *testing.T) {
|
||||
t.Run("no withdrawals", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(expected))
|
||||
})
|
||||
t.Run("one fully withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
nextWithdrawalValidatorIndex: 20,
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.validators[3].WithdrawableEpoch = primitives.Epoch(0)
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[3],
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one partially withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one partially and one fully withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
s.validators[7].WithdrawableEpoch = primitives.Epoch(0)
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, len(expected))
|
||||
for _, stateVersion := range []int{version.Capella, version.Deneb, version.Electra} {
|
||||
t.Run(version.String(stateVersion), func(t *testing.T) {
|
||||
t.Run("no withdrawals", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := range vals {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
vals[i] = val
|
||||
}
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(expected))
|
||||
})
|
||||
t.Run("one fully withdrawable", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
require.NoError(t, s.SetNextWithdrawalValidatorIndex(20))
|
||||
|
||||
withdrawalFull := &enginev1.Withdrawal{
|
||||
Index: 1,
|
||||
ValidatorIndex: 7,
|
||||
Address: s.validators[7].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[7],
|
||||
}
|
||||
withdrawalPartial := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawalPartial, expected[0])
|
||||
require.DeepEqual(t, withdrawalFull, expected[1])
|
||||
})
|
||||
t.Run("all partially withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance + 1
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := 0; i < 100; i++ {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
|
||||
vals[i] = val
|
||||
}
|
||||
vals[3].WithdrawableEpoch = primitives.Epoch(0)
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: vals[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one partially withdrawable", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
require.NoError(t, s.SetNextWithdrawalValidatorIndex(20))
|
||||
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := 0; i < 100; i++ {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
|
||||
vals[i] = val
|
||||
}
|
||||
balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: vals[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one partially and one fully withdrawable", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := range vals {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
vals[i] = val
|
||||
}
|
||||
balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
vals[7].WithdrawableEpoch = primitives.Epoch(0)
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, len(expected))
|
||||
|
||||
withdrawalFull := &enginev1.Withdrawal{
|
||||
Index: 1,
|
||||
ValidatorIndex: 7,
|
||||
Address: vals[7].WithdrawalCredentials[12:],
|
||||
Amount: balances[7],
|
||||
}
|
||||
withdrawalPartial := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: vals[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawalPartial, expected[0])
|
||||
require.DeepEqual(t, withdrawalFull, expected[1])
|
||||
})
|
||||
t.Run("all partially withdrawable", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := range vals {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance + 1
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
vals[i] = val
|
||||
}
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: vals[0].WithdrawalCredentials[12:],
|
||||
Amount: 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("all fully withdrawable", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := range vals {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(0),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
vals[i] = val
|
||||
}
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: vals[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("all fully and partially withdrawable", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := range vals {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance + 1
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(0),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
vals[i] = val
|
||||
}
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: vals[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance + 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one fully withdrawable but zero balance", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
require.NoError(t, s.SetNextWithdrawalValidatorIndex(20))
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := range vals {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
vals[i] = val
|
||||
}
|
||||
vals[3].WithdrawableEpoch = primitives.Epoch(0)
|
||||
balances[3] = 0
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(expected))
|
||||
})
|
||||
t.Run("one partially withdrawable, one above sweep bound", func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, stateVersion)
|
||||
vals := make([]*ethpb.Validator, 100)
|
||||
balances := make([]uint64, 100)
|
||||
for i := range vals {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
vals[i] = val
|
||||
}
|
||||
balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
balances[10] += params.BeaconConfig().MinDepositAmount
|
||||
require.NoError(t, s.SetValidators(vals))
|
||||
require.NoError(t, s.SetBalances(balances))
|
||||
saved := params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = 10
|
||||
expected, _, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: vals[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = saved
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("electra all pending partial withdrawals", func(t *testing.T) {
|
||||
// Load a serialized Electra state from disk.
|
||||
// This spectest has a fully hydrated beacon state with partial pending withdrawals.
|
||||
serializedBytes, err := util.BazelFileBytes("tests/mainnet/electra/operations/execution_layer_withdrawal_request/pyspec_tests/pending_withdrawals_consume_all_excess_balance/pre.ssz_snappy")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("all fully withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(0),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
serializedSSZ, err := snappy.Decode(nil /* dst */, serializedBytes)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("all fully and partially withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance + 1
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(0),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
pb := ðpb.BeaconStateElectra{}
|
||||
require.NoError(t, pb.UnmarshalSSZ(serializedSSZ))
|
||||
s, err := state_native.InitializeFromProtoElectra(pb)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance + 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one fully withdrawable but zero balance", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
nextWithdrawalValidatorIndex: 20,
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.validators[3].WithdrawableEpoch = primitives.Epoch(0)
|
||||
s.balances[3] = 0
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
t.Log(s.NumPendingPartialWithdrawals())
|
||||
expected, partialWithdrawalsCount, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(expected))
|
||||
})
|
||||
t.Run("one partially withdrawable, one above sweep bound", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Capella,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
s.balances[10] += params.BeaconConfig().MinDepositAmount
|
||||
saved := params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = 10
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = saved
|
||||
})
|
||||
}
|
||||
|
||||
func TestExpectedWithdrawals_Deneb(t *testing.T) {
|
||||
t.Run("no withdrawals", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(expected))
|
||||
})
|
||||
t.Run("one fully withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
nextWithdrawalValidatorIndex: 20,
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.validators[3].WithdrawableEpoch = primitives.Epoch(0)
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[3],
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one partially withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one partially and one fully withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials[31] = byte(i)
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
s.validators[7].WithdrawableEpoch = primitives.Epoch(0)
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, len(expected))
|
||||
|
||||
withdrawalFull := &enginev1.Withdrawal{
|
||||
Index: 1,
|
||||
ValidatorIndex: 7,
|
||||
Address: s.validators[7].WithdrawalCredentials[12:],
|
||||
Amount: s.balances[7],
|
||||
}
|
||||
withdrawalPartial := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawalPartial, expected[0])
|
||||
require.DeepEqual(t, withdrawalFull, expected[1])
|
||||
})
|
||||
t.Run("all partially withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance + 1
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("all fully withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(0),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("all fully and partially withdrawable", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance + 1
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(0),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxWithdrawalsPerPayload, uint64(len(expected)))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 0,
|
||||
Address: s.validators[0].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance + 1,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
})
|
||||
t.Run("one fully withdrawable but zero balance", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
nextWithdrawalValidatorIndex: 20,
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.validators[3].WithdrawableEpoch = primitives.Epoch(0)
|
||||
s.balances[3] = 0
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(expected))
|
||||
})
|
||||
t.Run("one partially withdrawable, one above sweep bound", func(t *testing.T) {
|
||||
s := BeaconState{
|
||||
version: version.Deneb,
|
||||
validators: make([]*ethpb.Validator, 100),
|
||||
balances: make([]uint64, 100),
|
||||
}
|
||||
for i := range s.validators {
|
||||
s.balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
val := ðpb.Validator{
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawableEpoch: primitives.Epoch(1),
|
||||
}
|
||||
val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
s.validators[i] = val
|
||||
}
|
||||
s.balances[3] += params.BeaconConfig().MinDepositAmount
|
||||
s.balances[10] += params.BeaconConfig().MinDepositAmount
|
||||
saved := params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = 10
|
||||
expected, err := s.ExpectedWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(expected))
|
||||
withdrawal := &enginev1.Withdrawal{
|
||||
Index: 0,
|
||||
ValidatorIndex: 3,
|
||||
Address: s.validators[3].WithdrawalCredentials[12:],
|
||||
Amount: params.BeaconConfig().MinDepositAmount,
|
||||
}
|
||||
require.DeepEqual(t, withdrawal, expected[0])
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = saved
|
||||
require.Equal(t, 8, len(expected))
|
||||
require.Equal(t, uint64(8), partialWithdrawalsCount)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package state_native
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
@@ -38,6 +39,10 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateCapellaFieldCount)
|
||||
case version.Deneb:
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateDenebFieldCount)
|
||||
case version.Electra:
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateElectraFieldCount)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown state version %s", version.String(state.version))
|
||||
}
|
||||
|
||||
// Genesis time root.
|
||||
@@ -247,6 +252,15 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
fieldRoots[types.LatestExecutionPayloadHeaderDeneb.RealPosition()] = executionPayloadRoot[:]
|
||||
}
|
||||
|
||||
if state.version == version.Electra {
|
||||
// Execution payload root.
|
||||
executionPayloadRoot, err := state.latestExecutionPayloadHeaderElectra.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldRoots[types.LatestExecutionPayloadHeaderElectra.RealPosition()] = executionPayloadRoot[:]
|
||||
}
|
||||
|
||||
if state.version >= version.Capella {
|
||||
// Next withdrawal index root.
|
||||
nextWithdrawalIndexRoot := make([]byte, 32)
|
||||
@@ -266,5 +280,52 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
fieldRoots[types.HistoricalSummaries.RealPosition()] = historicalSummaryRoot[:]
|
||||
}
|
||||
|
||||
if state.version >= version.Electra {
|
||||
// DepositReceiptsStartIndex root.
|
||||
drsiRoot := ssz.Uint64Root(state.depositReceiptsStartIndex)
|
||||
fieldRoots[types.DepositReceiptsStartIndex.RealPosition()] = drsiRoot[:]
|
||||
|
||||
// DepositBalanceToConsume root.
|
||||
dbtcRoot := ssz.Uint64Root(uint64(state.depositBalanceToConsume))
|
||||
fieldRoots[types.DepositBalanceToConsume.RealPosition()] = dbtcRoot[:]
|
||||
|
||||
// ExitBalanceToConsume root.
|
||||
ebtcRoot := ssz.Uint64Root(uint64(state.exitBalanceToConsume))
|
||||
fieldRoots[types.ExitBalanceToConsume.RealPosition()] = ebtcRoot[:]
|
||||
|
||||
// EarliestExitEpoch root.
|
||||
eeeRoot := ssz.Uint64Root(uint64(state.earliestExitEpoch))
|
||||
fieldRoots[types.EarliestExitEpoch.RealPosition()] = eeeRoot[:]
|
||||
|
||||
// ConsolidationBalanceToConsume root.
|
||||
cbtcRoot := ssz.Uint64Root(uint64(state.consolidationBalanceToConsume))
|
||||
fieldRoots[types.ConsolidationBalanceToConsume.RealPosition()] = cbtcRoot[:]
|
||||
|
||||
// EarliestConsolidationEpoch root.
|
||||
eceRoot := ssz.Uint64Root(uint64(state.earliestConsolidationEpoch))
|
||||
fieldRoots[types.EarliestConsolidationEpoch.RealPosition()] = eceRoot[:]
|
||||
|
||||
// PendingBalanceDeposits root.
|
||||
pbdRoot, err := stateutil.PendingBalanceDepositsRoot(state.pendingBalanceDeposits)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute pending balance deposits merkleization")
|
||||
}
|
||||
fieldRoots[types.PendingBalanceDeposits.RealPosition()] = pbdRoot[:]
|
||||
|
||||
// PendingPartialWithdrawals root.
|
||||
ppwRoot, err := stateutil.PendingPartialWithdrawalsRoot(state.pendingPartialWithdrawals)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute pending partial withdrawals merkleization")
|
||||
}
|
||||
fieldRoots[types.PendingPartialWithdrawals.RealPosition()] = ppwRoot[:]
|
||||
|
||||
// PendingConsolidations root.
|
||||
pcRoot, err := stateutil.PendingConsolidationsRoot(state.pendingConsolidations)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute pending consolidations merkleization")
|
||||
}
|
||||
fieldRoots[types.PendingConsolidations.RealPosition()] = pcRoot[:]
|
||||
}
|
||||
|
||||
return fieldRoots, nil
|
||||
}
|
||||
|
||||
67
beacon-chain/state/state-native/setters_balance_deposits.go
Normal file
67
beacon-chain/state/state-native/setters_balance_deposits.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// AppendPendingBalanceDeposit is a mutating call to the beacon state to create and append a pending
|
||||
// balance deposit object on to the state. This method requires access to the Lock on the state and
|
||||
// only applies in electra or later.
|
||||
func (b *BeaconState) AppendPendingBalanceDeposit(index primitives.ValidatorIndex, amount uint64) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("AppendPendingBalanceDeposit", b.version)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[types.PendingBalanceDeposits].MinusRef()
|
||||
b.sharedFieldReferences[types.PendingBalanceDeposits] = stateutil.NewRef(1)
|
||||
|
||||
b.pendingBalanceDeposits = append(b.pendingBalanceDeposits, ðpb.PendingBalanceDeposit{Index: index, Amount: amount})
|
||||
|
||||
b.markFieldAsDirty(types.PendingBalanceDeposits)
|
||||
b.rebuildTrie[types.PendingBalanceDeposits] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPendingBalanceDeposits is a mutating call to the beacon state which replaces the pending
|
||||
// balance deposit slice with the provided value. This method requires access to the Lock on the
|
||||
// state and only applies in electra or later.
|
||||
func (b *BeaconState) SetPendingBalanceDeposits(val []*ethpb.PendingBalanceDeposit) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetPendingBalanceDeposits", b.version)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[types.PendingBalanceDeposits].MinusRef()
|
||||
b.sharedFieldReferences[types.PendingBalanceDeposits] = stateutil.NewRef(1)
|
||||
|
||||
b.pendingBalanceDeposits = val
|
||||
|
||||
b.markFieldAsDirty(types.PendingBalanceDeposits)
|
||||
b.rebuildTrie[types.PendingBalanceDeposits] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetDepositBalanceToConsume is a mutating call to the beacon state which sets the deposit balance
|
||||
// to consume value to the given value. This method requires access to the Lock on the state and
|
||||
// only applies in electra or later.
|
||||
func (b *BeaconState) SetDepositBalanceToConsume(dbtc math.Gwei) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetDepositBalanceToConsume", b.version)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.depositBalanceToConsume = dbtc
|
||||
|
||||
b.markFieldAsDirty(types.DepositBalanceToConsume)
|
||||
b.rebuildTrie[types.DepositBalanceToConsume] = true
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestAppendPendingBalanceDeposit(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{})
|
||||
require.NoError(t, err)
|
||||
pbd, err := s.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(pbd))
|
||||
require.NoError(t, s.AppendPendingBalanceDeposit(1, 10))
|
||||
pbd, err = s.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(pbd))
|
||||
require.Equal(t, primitives.ValidatorIndex(1), pbd[0].Index)
|
||||
require.Equal(t, uint64(10), pbd[0].Amount)
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "not supported", s.AppendPendingBalanceDeposit(1, 1))
|
||||
}
|
||||
|
||||
func TestSetPendingBalanceDeposits(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{})
|
||||
require.NoError(t, err)
|
||||
pbd, err := s.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(pbd))
|
||||
require.NoError(t, s.SetPendingBalanceDeposits([]*eth.PendingBalanceDeposit{{}, {}, {}}))
|
||||
pbd, err = s.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 3, len(pbd))
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "not supported", s.SetPendingBalanceDeposits([]*eth.PendingBalanceDeposit{{}, {}, {}}))
|
||||
}
|
||||
|
||||
func TestSetDepositBalanceToConsume(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetDepositBalanceToConsume(10))
|
||||
dbtc, err := s.DepositBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, math.Gwei(10), dbtc)
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "not supported", s.SetDepositBalanceToConsume(10))
|
||||
}
|
||||
80
beacon-chain/state/state-native/setters_churn.go
Normal file
80
beacon-chain/state/state-native/setters_churn.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
|
||||
// ExitEpochAndUpdateChurn computes the exit epoch and updates the churn. This method mutates the state.
|
||||
//
|
||||
// Spec definition:
|
||||
//
|
||||
// def compute_exit_epoch_and_update_churn(state: BeaconState, exit_balance: Gwei) -> Epoch:
|
||||
// earliest_exit_epoch = max(state.earliest_exit_epoch, compute_activation_exit_epoch(get_current_epoch(state)))
|
||||
// per_epoch_churn = get_activation_exit_churn_limit(state)
|
||||
// # New epoch for exits.
|
||||
// if state.earliest_exit_epoch < earliest_exit_epoch:
|
||||
// exit_balance_to_consume = per_epoch_churn
|
||||
// else:
|
||||
// exit_balance_to_consume = state.exit_balance_to_consume
|
||||
//
|
||||
// # Exit doesn't fit in the current earliest epoch.
|
||||
// if exit_balance > exit_balance_to_consume:
|
||||
// balance_to_process = exit_balance - exit_balance_to_consume
|
||||
// additional_epochs = (balance_to_process - 1) // per_epoch_churn + 1
|
||||
// earliest_exit_epoch += additional_epochs
|
||||
// exit_balance_to_consume += additional_epochs * per_epoch_churn
|
||||
//
|
||||
// # Consume the balance and update state variables.
|
||||
// state.exit_balance_to_consume = exit_balance_to_consume - exit_balance
|
||||
// state.earliest_exit_epoch = earliest_exit_epoch
|
||||
//
|
||||
// return state.earliest_exit_epoch
|
||||
func (b *BeaconState) ExitEpochAndUpdateChurn(exitBalance math.Gwei) (primitives.Epoch, error) {
|
||||
if b.version < version.Electra {
|
||||
return 0, errNotSupported("ExitEpochAndUpdateChurn", b.version)
|
||||
}
|
||||
|
||||
// This helper requires access to the RLock and cannot be called from within the write Lock.
|
||||
activeBal, err := helpers.TotalActiveBalance(b)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
earliestExitEpoch := max(b.earliestExitEpoch, helpers.ActivationExitEpoch(slots.ToEpoch(b.slot)))
|
||||
perEpochChurn := helpers.ActivationExitChurnLimit(math.Gwei(activeBal)) // Guaranteed to be non-zero.
|
||||
|
||||
// New epoch for exits
|
||||
var exitBalanceToConsume math.Gwei
|
||||
if b.earliestExitEpoch < earliestExitEpoch {
|
||||
exitBalanceToConsume = perEpochChurn
|
||||
} else {
|
||||
exitBalanceToConsume = b.exitBalanceToConsume
|
||||
}
|
||||
|
||||
// Exit doesn't fit in the current earliest epoch.
|
||||
if exitBalance > exitBalanceToConsume {
|
||||
balanceToProcess := exitBalance - exitBalanceToConsume
|
||||
additionalEpochs := primitives.Epoch((balanceToProcess-1)/perEpochChurn + 1)
|
||||
earliestExitEpoch += additionalEpochs
|
||||
exitBalanceToConsume += math.Gwei(additionalEpochs) * perEpochChurn
|
||||
}
|
||||
|
||||
// Consume the balance and update state variables.
|
||||
b.exitBalanceToConsume = exitBalanceToConsume - exitBalance
|
||||
b.earliestExitEpoch = earliestExitEpoch
|
||||
|
||||
b.markFieldAsDirty(types.ExitBalanceToConsume)
|
||||
b.rebuildTrie[types.ExitBalanceToConsume] = true
|
||||
b.markFieldAsDirty(types.EarliestExitEpoch)
|
||||
b.rebuildTrie[types.EarliestExitEpoch] = true
|
||||
|
||||
return b.earliestExitEpoch, nil
|
||||
}
|
||||
200
beacon-chain/state/state-native/setters_churn_test.go
Normal file
200
beacon-chain/state/state-native/setters_churn_test.go
Normal file
@@ -0,0 +1,200 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
|
||||
func TestExitEpochAndUpdateChurn_SpectestCase(t *testing.T) {
|
||||
// Load a serialized Electra state from disk.
|
||||
// The spec tests shows that the exit epoch is 262 for validator 0 performing a voluntary exit.
|
||||
serializedBytes, err := util.BazelFileBytes("tests/mainnet/electra/operations/voluntary_exit/pyspec_tests/exit_existing_churn_and_churn_limit_balance/pre.ssz_snappy")
|
||||
require.NoError(t, err)
|
||||
serializedSSZ, err := snappy.Decode(nil /* dst */, serializedBytes)
|
||||
require.NoError(t, err)
|
||||
pb := ð.BeaconStateElectra{}
|
||||
require.NoError(t, pb.UnmarshalSSZ(serializedSSZ))
|
||||
s, err := state_native.InitializeFromProtoElectra(pb)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, err := s.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
|
||||
ee, err := s.ExitEpochAndUpdateChurn(math.Gwei(val.EffectiveBalance))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, primitives.Epoch(262), ee)
|
||||
|
||||
p := s.ToProto()
|
||||
pb, ok := p.(*eth.BeaconStateElectra)
|
||||
if !ok {
|
||||
t.Fatal("wrong proto")
|
||||
}
|
||||
require.Equal(t, math.Gwei(127000000000), pb.ExitBalanceToConsume)
|
||||
require.Equal(t, primitives.Epoch(262), pb.EarliestExitEpoch)
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
_, err = s.ExitEpochAndUpdateChurn(10)
|
||||
require.ErrorContains(t, "not supported", err)
|
||||
}
|
||||
|
||||
func TestExitEpochAndUpdateChurn(t *testing.T) {
|
||||
slot := primitives.Slot(10_000_000)
|
||||
epoch := slots.ToEpoch(slot)
|
||||
t.Run("state earliest exit epoch is old", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
Slot: slot,
|
||||
Validators: []*eth.Validator{
|
||||
{
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra,
|
||||
},
|
||||
},
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalanceElectra},
|
||||
EarliestExitEpoch: epoch - params.BeaconConfig().MaxSeedLookahead*2, // Old, relative to slot.
|
||||
ExitBalanceToConsume: math.Gwei(20_000_000),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
activeBal, err := helpers.TotalActiveBalance(st)
|
||||
require.NoError(t, err)
|
||||
|
||||
exitBal := math.Gwei(10_000_000)
|
||||
|
||||
wantExitBalToConsume := helpers.ActivationExitChurnLimit(math.Gwei(activeBal)) - exitBal
|
||||
|
||||
ee, err := st.ExitEpochAndUpdateChurn(exitBal)
|
||||
require.NoError(t, err)
|
||||
|
||||
wantExitEpoch := helpers.ActivationExitEpoch(epoch)
|
||||
require.Equal(t, wantExitEpoch, ee)
|
||||
|
||||
p := st.ToProto()
|
||||
pb, ok := p.(*eth.BeaconStateElectra)
|
||||
if !ok {
|
||||
t.Fatal("wrong proto")
|
||||
}
|
||||
require.Equal(t, wantExitBalToConsume, pb.ExitBalanceToConsume)
|
||||
require.Equal(t, wantExitEpoch, pb.EarliestExitEpoch)
|
||||
})
|
||||
|
||||
t.Run("state exit bal to consume is less than activation exit churn limit", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
Slot: slot,
|
||||
Validators: []*eth.Validator{
|
||||
{
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra,
|
||||
},
|
||||
},
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalanceElectra},
|
||||
EarliestExitEpoch: epoch,
|
||||
ExitBalanceToConsume: math.Gwei(20_000_000),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
activeBal, err := helpers.TotalActiveBalance(st)
|
||||
require.NoError(t, err)
|
||||
|
||||
activationExitChurnLimit := helpers.ActivationExitChurnLimit(math.Gwei(activeBal))
|
||||
exitBal := activationExitChurnLimit * 2
|
||||
|
||||
wantExitBalToConsume := math.Gwei(0)
|
||||
|
||||
ee, err := st.ExitEpochAndUpdateChurn(exitBal)
|
||||
require.NoError(t, err)
|
||||
|
||||
wantExitEpoch := helpers.ActivationExitEpoch(epoch) + 1
|
||||
require.Equal(t, wantExitEpoch, ee)
|
||||
|
||||
p := st.ToProto()
|
||||
pb, ok := p.(*eth.BeaconStateElectra)
|
||||
if !ok {
|
||||
t.Fatal("wrong proto")
|
||||
}
|
||||
require.Equal(t, wantExitBalToConsume, pb.ExitBalanceToConsume)
|
||||
require.Equal(t, wantExitEpoch, pb.EarliestExitEpoch)
|
||||
})
|
||||
|
||||
t.Run("state earliest exit epoch is in the future and exit balance is less than state", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
Slot: slot,
|
||||
Validators: []*eth.Validator{
|
||||
{
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra,
|
||||
},
|
||||
},
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalanceElectra},
|
||||
EarliestExitEpoch: epoch + 10_000,
|
||||
ExitBalanceToConsume: math.Gwei(20_000_000),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
exitBal := math.Gwei(10_000_000)
|
||||
|
||||
wantExitBalToConsume := math.Gwei(20_000_000) - exitBal
|
||||
|
||||
ee, err := st.ExitEpochAndUpdateChurn(exitBal)
|
||||
require.NoError(t, err)
|
||||
|
||||
wantExitEpoch := epoch + 10_000
|
||||
require.Equal(t, wantExitEpoch, ee)
|
||||
|
||||
p := st.ToProto()
|
||||
pb, ok := p.(*eth.BeaconStateElectra)
|
||||
if !ok {
|
||||
t.Fatal("wrong proto")
|
||||
}
|
||||
require.Equal(t, wantExitBalToConsume, pb.ExitBalanceToConsume)
|
||||
require.Equal(t, wantExitEpoch, pb.EarliestExitEpoch)
|
||||
})
|
||||
|
||||
t.Run("state earliest exit epoch is in the future and exit balance exceeds state", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
Slot: slot,
|
||||
Validators: []*eth.Validator{
|
||||
{
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra,
|
||||
},
|
||||
},
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalanceElectra},
|
||||
EarliestExitEpoch: epoch + 10_000,
|
||||
ExitBalanceToConsume: math.Gwei(20_000_000),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
exitBal := math.Gwei(40_000_000)
|
||||
activeBal, err := helpers.TotalActiveBalance(st)
|
||||
require.NoError(t, err)
|
||||
activationExitChurnLimit := helpers.ActivationExitChurnLimit(math.Gwei(activeBal))
|
||||
wantExitBalToConsume := activationExitChurnLimit - 20_000_000
|
||||
|
||||
ee, err := st.ExitEpochAndUpdateChurn(exitBal)
|
||||
require.NoError(t, err)
|
||||
|
||||
wantExitEpoch := epoch + 10_000 + 1
|
||||
require.Equal(t, wantExitEpoch, ee)
|
||||
|
||||
p := st.ToProto()
|
||||
pb, ok := p.(*eth.BeaconStateElectra)
|
||||
if !ok {
|
||||
t.Fatal("wrong proto")
|
||||
}
|
||||
require.Equal(t, wantExitBalToConsume, pb.ExitBalanceToConsume)
|
||||
require.Equal(t, wantExitEpoch, pb.EarliestExitEpoch)
|
||||
})
|
||||
|
||||
t.Run("earlier than electra returns error", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
_, err = st.ExitEpochAndUpdateChurn(0)
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
}
|
||||
84
beacon-chain/state/state-native/setters_consolidation.go
Normal file
84
beacon-chain/state/state-native/setters_consolidation.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// AppendPendingConsolidation is a mutating call to the beacon state which appends the provided
|
||||
// pending consolidation to the end of the slice on the state. This method requires access to the
|
||||
// Lock on the state and only applies in electra or later.
|
||||
func (b *BeaconState) AppendPendingConsolidation(val *ethpb.PendingConsolidation) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("AppendPendingConsolidation", b.version)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[types.PendingConsolidations].MinusRef()
|
||||
b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1)
|
||||
|
||||
b.pendingConsolidations = append(b.pendingConsolidations, val)
|
||||
|
||||
b.markFieldAsDirty(types.PendingConsolidations)
|
||||
b.rebuildTrie[types.PendingConsolidations] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPendingConsolidations is a mutating call to the beacon state which replaces the slice on the
|
||||
// state with the given value. This method requires access to the Lock on the state and only applies
|
||||
// in electra or later.
|
||||
func (b *BeaconState) SetPendingConsolidations(val []*ethpb.PendingConsolidation) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetPendingConsolidations", b.version)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[types.PendingConsolidations].MinusRef()
|
||||
b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1)
|
||||
|
||||
b.pendingConsolidations = val
|
||||
|
||||
b.markFieldAsDirty(types.PendingConsolidations)
|
||||
b.rebuildTrie[types.PendingConsolidations] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetEarliestConsolidationEpoch is a mutating call to the beacon state which sets the earlest
|
||||
// consolidation epoch value. This method requires access to the Lock on the state and only applies
|
||||
// in electra or later.
|
||||
func (b *BeaconState) SetEarliestConsolidationEpoch(epoch primitives.Epoch) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetEarliestConsolidationEpoch", b.version)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.earliestConsolidationEpoch = epoch
|
||||
|
||||
b.markFieldAsDirty(types.EarliestConsolidationEpoch)
|
||||
b.rebuildTrie[types.EarliestConsolidationEpoch] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetConsolidationBalanceToConsume is a mutating call to the beacon state which sets the value of
|
||||
// the consolidation balance to consume to the provided value. This method requires access to the
|
||||
// Lock on the state and only applies in electra or later.
|
||||
func (b *BeaconState) SetConsolidationBalanceToConsume(balance math.Gwei) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetConsolidationBalanceToConsume", b.version)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.consolidationBalanceToConsume = balance
|
||||
|
||||
b.markFieldAsDirty(types.ConsolidationBalanceToConsume)
|
||||
b.rebuildTrie[types.ConsolidationBalanceToConsume] = true
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func TestAppendPendingConsolidation(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{})
|
||||
require.NoError(t, err)
|
||||
num, err := s.NumPendingConsolidations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), num)
|
||||
require.NoError(t, s.AppendPendingConsolidation(ð.PendingConsolidation{}))
|
||||
num, err = s.NumPendingConsolidations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), num)
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "not supported", s.AppendPendingConsolidation(ð.PendingConsolidation{}))
|
||||
}
|
||||
|
||||
func TestSetPendingConsolidations(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{})
|
||||
require.NoError(t, err)
|
||||
num, err := s.NumPendingConsolidations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), num)
|
||||
require.NoError(t, s.SetPendingConsolidations([]*eth.PendingConsolidation{{}, {}, {}}))
|
||||
num, err = s.NumPendingConsolidations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(3), num)
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "not supported", s.SetPendingConsolidations([]*eth.PendingConsolidation{{}, {}, {}}))
|
||||
}
|
||||
|
||||
func TestSetEarliestConsolidationEpoch(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{})
|
||||
require.NoError(t, err)
|
||||
ece, err := s.EarliestConsolidationEpoch()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, primitives.Epoch(0), ece)
|
||||
require.NoError(t, s.SetEarliestConsolidationEpoch(10))
|
||||
ece, err = s.EarliestConsolidationEpoch()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, primitives.Epoch(10), ece)
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "not supported", s.SetEarliestConsolidationEpoch(10))
|
||||
}
|
||||
|
||||
func TestSetConsolidationBalanceToConsume(t *testing.T) {
|
||||
s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetConsolidationBalanceToConsume(10))
|
||||
cbtc, err := s.ConsolidationBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, math.Gwei(10), cbtc)
|
||||
|
||||
// Fails for versions older than electra
|
||||
s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "not supported", s.SetConsolidationBalanceToConsume(10))
|
||||
}
|
||||
21
beacon-chain/state/state-native/setters_deposit_receipts.go
Normal file
21
beacon-chain/state/state-native/setters_deposit_receipts.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// SetDepositReceiptsStartIndex for the beacon state. Updates the DepositReceiptsStartIndex
|
||||
func (b *BeaconState) SetDepositReceiptsStartIndex(index uint64) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("SetDepositReceiptsStartIndex", b.version)
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.depositReceiptsStartIndex = index
|
||||
b.markFieldAsDirty(types.DepositReceiptsStartIndex)
|
||||
b.rebuildTrie[types.DepositReceiptsStartIndex] = true
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestSetDepositReceiptsStartIndex(t *testing.T) {
|
||||
t.Run("previous fork returns expected error", func(t *testing.T) {
|
||||
dState, _ := util.DeterministicGenesisState(t, 1)
|
||||
require.ErrorContains(t, "is not supported", dState.SetDepositReceiptsStartIndex(1))
|
||||
})
|
||||
t.Run("electra sets expected value", func(t *testing.T) {
|
||||
old := uint64(2)
|
||||
dState, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{DepositReceiptsStartIndex: old})
|
||||
require.NoError(t, err)
|
||||
want := uint64(3)
|
||||
require.NoError(t, dState.SetDepositReceiptsStartIndex(want))
|
||||
got, err := dState.DepositReceiptsStartIndex()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
@@ -21,6 +23,9 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa
|
||||
|
||||
switch header := val.Proto().(type) {
|
||||
case *enginev1.ExecutionPayload:
|
||||
if b.version != version.Bellatrix {
|
||||
return fmt.Errorf("wrong state version (%s) for bellatrix execution payload", version.String(b.version))
|
||||
}
|
||||
latest, err := consensusblocks.PayloadToHeader(val)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert payload to header")
|
||||
@@ -29,6 +34,9 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeader)
|
||||
return nil
|
||||
case *enginev1.ExecutionPayloadCapella:
|
||||
if b.version != version.Capella {
|
||||
return fmt.Errorf("wrong state version (%s) for capella execution payload", version.String(b.version))
|
||||
}
|
||||
latest, err := consensusblocks.PayloadToHeaderCapella(val)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert payload to header")
|
||||
@@ -37,6 +45,9 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeaderCapella)
|
||||
return nil
|
||||
case *enginev1.ExecutionPayloadDeneb:
|
||||
if b.version != version.Deneb {
|
||||
return fmt.Errorf("wrong state version (%s) for deneb execution payload", version.String(b.version))
|
||||
}
|
||||
latest, err := consensusblocks.PayloadToHeaderDeneb(val)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert payload to header")
|
||||
@@ -44,18 +55,49 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa
|
||||
b.latestExecutionPayloadHeaderDeneb = latest
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeaderDeneb)
|
||||
return nil
|
||||
case *enginev1.ExecutionPayloadElectra:
|
||||
if b.version != version.Electra {
|
||||
return fmt.Errorf("wrong state version (%s) for electra execution payload", version.String(b.version))
|
||||
}
|
||||
eVal, ok := val.(interfaces.ExecutionDataElectra)
|
||||
if !ok {
|
||||
return fmt.Errorf("could not cast %T to ExecutionDataElectra: %w", val, interfaces.ErrInvalidCast)
|
||||
}
|
||||
latest, err := consensusblocks.PayloadToHeaderElectra(eVal)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert payload to header")
|
||||
}
|
||||
b.latestExecutionPayloadHeaderElectra = latest
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeaderElectra)
|
||||
return nil
|
||||
case *enginev1.ExecutionPayloadHeader:
|
||||
if b.version != version.Bellatrix {
|
||||
return fmt.Errorf("wrong state version (%s) for bellatrix execution payload header", version.String(b.version))
|
||||
}
|
||||
b.latestExecutionPayloadHeader = header
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeader)
|
||||
return nil
|
||||
case *enginev1.ExecutionPayloadHeaderCapella:
|
||||
if b.version != version.Capella {
|
||||
return fmt.Errorf("wrong state version (%s) for capella execution payload header", version.String(b.version))
|
||||
}
|
||||
b.latestExecutionPayloadHeaderCapella = header
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeaderCapella)
|
||||
return nil
|
||||
case *enginev1.ExecutionPayloadHeaderDeneb:
|
||||
if b.version != version.Deneb {
|
||||
return fmt.Errorf("wrong state version (%s) for deneb execution payload header", version.String(b.version))
|
||||
}
|
||||
b.latestExecutionPayloadHeaderDeneb = header
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeaderDeneb)
|
||||
return nil
|
||||
case *enginev1.ExecutionPayloadHeaderElectra:
|
||||
if b.version != version.Electra {
|
||||
return fmt.Errorf("wrong state version (%s) for electra execution payload header", version.String(b.version))
|
||||
}
|
||||
b.latestExecutionPayloadHeaderElectra = header
|
||||
b.markFieldAsDirty(types.LatestExecutionPayloadHeaderElectra)
|
||||
return nil
|
||||
default:
|
||||
return errors.New("value must be an execution payload header")
|
||||
}
|
||||
|
||||
107
beacon-chain/state/state-native/setters_payload_header_test.go
Normal file
107
beacon-chain/state/state-native/setters_payload_header_test.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
)
|
||||
|
||||
func TestSetLatestExecutionPayloadHeader(t *testing.T) {
|
||||
versionOffset := version.Bellatrix // PayloadHeader only applies in Bellatrix and beyond.
|
||||
payloads := []interfaces.ExecutionData{
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBeaconBlockBellatrix().Block.Body.ExecutionPayload
|
||||
ee, err := blocks.WrappedExecutionPayload(e)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBeaconBlockCapella().Block.Body.ExecutionPayload
|
||||
ee, err := blocks.WrappedExecutionPayloadCapella(e, nil)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBeaconBlockDeneb().Block.Body.ExecutionPayload
|
||||
ee, err := blocks.WrappedExecutionPayloadDeneb(e, nil)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBeaconBlockElectra().Block.Body.ExecutionPayload
|
||||
ee, err := blocks.WrappedExecutionPayloadElectra(e, nil)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
}
|
||||
|
||||
payloadHeaders := []interfaces.ExecutionData{
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBlindedBeaconBlockBellatrix().Block.Body.ExecutionPayloadHeader
|
||||
ee, err := blocks.WrappedExecutionPayloadHeader(e)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBlindedBeaconBlockCapella().Block.Body.ExecutionPayloadHeader
|
||||
ee, err := blocks.WrappedExecutionPayloadHeaderCapella(e, nil)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBlindedBeaconBlockDeneb().Message.Body.ExecutionPayloadHeader
|
||||
ee, err := blocks.WrappedExecutionPayloadHeaderDeneb(e, nil)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
func() interfaces.ExecutionData {
|
||||
e := util.NewBlindedBeaconBlockElectra().Message.Body.ExecutionPayloadHeader
|
||||
ee, err := blocks.WrappedExecutionPayloadHeaderElectra(e, nil)
|
||||
require.NoError(t, err)
|
||||
return ee
|
||||
}(),
|
||||
}
|
||||
|
||||
t.Run("can set payload", func(t *testing.T) {
|
||||
for i, p := range payloads {
|
||||
t.Run(version.String(i+versionOffset), func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, i+versionOffset)
|
||||
require.NoError(t, s.SetLatestExecutionPayloadHeader(p))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("can set payload header", func(t *testing.T) {
|
||||
for i, ph := range payloadHeaders {
|
||||
t.Run(version.String(i+versionOffset), func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, i+versionOffset)
|
||||
require.NoError(t, s.SetLatestExecutionPayloadHeader(ph))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("mismatched type version returns error", func(t *testing.T) {
|
||||
require.Equal(t, len(payloads), len(payloadHeaders), "This test will fail if the payloads and payload headers are not same length")
|
||||
for i := 0; i < len(payloads); i++ {
|
||||
for j := 0; j < len(payloads); j++ {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
t.Run(fmt.Sprintf("%s state with %s payload", version.String(i+versionOffset), version.String(j+versionOffset)), func(t *testing.T) {
|
||||
s := state_native.EmptyStateFromVersion(t, i+versionOffset)
|
||||
p := payloads[j]
|
||||
require.ErrorContains(t, "wrong state version", s.SetLatestExecutionPayloadHeader(p))
|
||||
ph := payloadHeaders[j]
|
||||
require.ErrorContains(t, "wrong state version", s.SetLatestExecutionPayloadHeader(ph))
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
@@ -34,3 +38,56 @@ func (b *BeaconState) SetNextWithdrawalValidatorIndex(i primitives.ValidatorInde
|
||||
b.markFieldAsDirty(types.NextWithdrawalValidatorIndex)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendPendingPartialWithdrawal is a mutating call to the beacon state which appends the given
|
||||
// value to the end of the pending partial withdrawals slice in the state. This method requires
|
||||
// access to the Lock on the state and only applies in electra or later.
|
||||
func (b *BeaconState) AppendPendingPartialWithdrawal(ppw *eth.PendingPartialWithdrawal) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("AppendPendingPartialWithdrawal", b.version)
|
||||
}
|
||||
|
||||
if ppw == nil {
|
||||
return errors.New("cannot append nil pending partial withdrawal")
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[types.PendingPartialWithdrawals].MinusRef()
|
||||
b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1)
|
||||
|
||||
b.pendingPartialWithdrawals = append(b.pendingPartialWithdrawals, ppw)
|
||||
|
||||
b.markFieldAsDirty(types.PendingPartialWithdrawals)
|
||||
b.rebuildTrie[types.PendingPartialWithdrawals] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// DequeuePartialWithdrawals removes the partial withdrawals from the beginning of the partial withdrawals list.
|
||||
func (b *BeaconState) DequeuePartialWithdrawals(n uint64) error {
|
||||
if b.version < version.Electra {
|
||||
return errNotSupported("DequeuePartialWithdrawals", b.version)
|
||||
}
|
||||
|
||||
if n > uint64(len(b.pendingPartialWithdrawals)) {
|
||||
return errors.New("cannot dequeue more withdrawals than are in the queue")
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return nil // Don't wait on a lock for no reason.
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[types.PendingPartialWithdrawals].MinusRef()
|
||||
b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1)
|
||||
|
||||
b.pendingPartialWithdrawals = b.pendingPartialWithdrawals[n:]
|
||||
|
||||
b.markFieldAsDirty(types.PendingPartialWithdrawals)
|
||||
b.rebuildTrie[types.PendingPartialWithdrawals] = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
@@ -52,3 +53,68 @@ func TestSetNextWithdrawalValidatorIndex_Deneb(t *testing.T) {
|
||||
require.Equal(t, primitives.ValidatorIndex(5), s.nextWithdrawalValidatorIndex)
|
||||
require.Equal(t, true, s.dirtyFields[types.NextWithdrawalValidatorIndex])
|
||||
}
|
||||
|
||||
func TestDequeuePendingWithdrawals(t *testing.T) {
|
||||
s, err := InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
PendingPartialWithdrawals: []*eth.PendingPartialWithdrawal{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// 2 of 3 should be OK
|
||||
num, err := s.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(3), num)
|
||||
require.NoError(t, s.DequeuePartialWithdrawals(2))
|
||||
num, err = s.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), num)
|
||||
|
||||
// 2 of 1 exceeds the limit and an error should be returned
|
||||
num, err = s.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), num)
|
||||
require.ErrorContains(t, "cannot dequeue more withdrawals than are in the queue", s.DequeuePartialWithdrawals(2))
|
||||
|
||||
// Removing all pending partial withdrawals should be OK.
|
||||
num, err = s.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), num)
|
||||
require.NoError(t, s.DequeuePartialWithdrawals(1))
|
||||
num, err = s.Copy().NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), num)
|
||||
|
||||
s, err = InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.ErrorContains(t, "is not supported", s.DequeuePartialWithdrawals(0))
|
||||
}
|
||||
|
||||
func TestAppendPendingWithdrawals(t *testing.T) {
|
||||
s, err := InitializeFromProtoElectra(ð.BeaconStateElectra{
|
||||
PendingPartialWithdrawals: []*eth.PendingPartialWithdrawal{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
num, err := s.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(3), num)
|
||||
require.NoError(t, s.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{}))
|
||||
num, err = s.NumPendingPartialWithdrawals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(4), num)
|
||||
|
||||
require.ErrorContains(t, "cannot append nil pending partial withdrawal", s.AppendPendingPartialWithdrawal(nil))
|
||||
|
||||
s, err = InitializeFromProtoDeneb(ð.BeaconStateDeneb{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.ErrorContains(t, "is not supported", s.AppendPendingPartialWithdrawal(nil))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
func (b *BeaconState) ProportionalSlashingMultiplier() (uint64, error) {
|
||||
switch b.version {
|
||||
case version.Bellatrix, version.Capella, version.Deneb:
|
||||
case version.Bellatrix, version.Capella, version.Deneb, version.Electra:
|
||||
return params.BeaconConfig().ProportionalSlashingMultiplierBellatrix, nil
|
||||
case version.Altair:
|
||||
return params.BeaconConfig().ProportionalSlashingMultiplierAltair, nil
|
||||
@@ -19,7 +19,7 @@ func (b *BeaconState) ProportionalSlashingMultiplier() (uint64, error) {
|
||||
|
||||
func (b *BeaconState) InactivityPenaltyQuotient() (uint64, error) {
|
||||
switch b.version {
|
||||
case version.Bellatrix, version.Capella, version.Deneb:
|
||||
case version.Bellatrix, version.Capella, version.Deneb, version.Electra:
|
||||
return params.BeaconConfig().InactivityPenaltyQuotientBellatrix, nil
|
||||
case version.Altair:
|
||||
return params.BeaconConfig().InactivityPenaltyQuotientAltair, nil
|
||||
|
||||
@@ -502,3 +502,13 @@ func generateState(t *testing.T) state.BeaconState {
|
||||
assert.NoError(t, err)
|
||||
return newState
|
||||
}
|
||||
|
||||
func EmptyStateFromVersion(t *testing.T, v int) state.BeaconState {
|
||||
gen := generateState(t)
|
||||
s, ok := gen.(*BeaconState)
|
||||
if !ok {
|
||||
t.Fatal("not a beacon state")
|
||||
}
|
||||
s.version = v
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package state_native
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
|
||||
@@ -93,17 +94,36 @@ var denebFields = append(
|
||||
types.HistoricalSummaries,
|
||||
)
|
||||
|
||||
var electraFields = append(
|
||||
altairFields,
|
||||
types.NextWithdrawalIndex,
|
||||
types.NextWithdrawalValidatorIndex,
|
||||
types.HistoricalSummaries,
|
||||
types.LatestExecutionPayloadHeaderElectra,
|
||||
types.DepositReceiptsStartIndex,
|
||||
types.DepositBalanceToConsume,
|
||||
types.ExitBalanceToConsume,
|
||||
types.EarliestExitEpoch,
|
||||
types.ConsolidationBalanceToConsume,
|
||||
types.EarliestConsolidationEpoch,
|
||||
types.PendingBalanceDeposits,
|
||||
types.PendingPartialWithdrawals,
|
||||
types.PendingConsolidations,
|
||||
)
|
||||
|
||||
const (
|
||||
phase0SharedFieldRefCount = 10
|
||||
altairSharedFieldRefCount = 11
|
||||
bellatrixSharedFieldRefCount = 12
|
||||
capellaSharedFieldRefCount = 14
|
||||
denebSharedFieldRefCount = 14
|
||||
electraSharedFieldRefCount = 17
|
||||
experimentalStatePhase0SharedFieldRefCount = 5
|
||||
experimentalStateAltairSharedFieldRefCount = 5
|
||||
experimentalStateBellatrixSharedFieldRefCount = 6
|
||||
experimentalStateCapellaSharedFieldRefCount = 8
|
||||
experimentalStateDenebSharedFieldRefCount = 8
|
||||
experimentalStateElectraSharedFieldRefCount = 11
|
||||
)
|
||||
|
||||
// InitializeFromProtoPhase0 the beacon state from a protobuf representation.
|
||||
@@ -131,6 +151,10 @@ func InitializeFromProtoDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconState, er
|
||||
return InitializeFromProtoUnsafeDeneb(proto.Clone(st).(*ethpb.BeaconStateDeneb))
|
||||
}
|
||||
|
||||
func InitializeFromProtoElectra(st *ethpb.BeaconStateElectra) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeElectra(proto.Clone(st).(*ethpb.BeaconStateElectra))
|
||||
}
|
||||
|
||||
// InitializeFromProtoUnsafePhase0 directly uses the beacon state protobuf fields
|
||||
// and sets them as fields of the BeaconState type.
|
||||
func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState, error) {
|
||||
@@ -683,6 +707,131 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// InitializeFromProtoUnsafeElectra directly uses the beacon state protobuf fields
|
||||
// and sets them as fields of the BeaconState type.
|
||||
func InitializeFromProtoUnsafeElectra(st *ethpb.BeaconStateElectra) (state.BeaconState, error) {
|
||||
if st == nil {
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots)))
|
||||
for i, r := range st.HistoricalRoots {
|
||||
hRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
|
||||
fieldCount := params.BeaconConfig().BeaconStateElectraFieldCount
|
||||
b := &BeaconState{
|
||||
version: version.Electra,
|
||||
genesisTime: st.GenesisTime,
|
||||
genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot),
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
eth1DataVotes: st.Eth1DataVotes,
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
slashings: st.Slashings,
|
||||
previousEpochParticipation: st.PreviousEpochParticipation,
|
||||
currentEpochParticipation: st.CurrentEpochParticipation,
|
||||
justificationBits: st.JustificationBits,
|
||||
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
|
||||
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
|
||||
finalizedCheckpoint: st.FinalizedCheckpoint,
|
||||
currentSyncCommittee: st.CurrentSyncCommittee,
|
||||
nextSyncCommittee: st.NextSyncCommittee,
|
||||
latestExecutionPayloadHeaderElectra: st.LatestExecutionPayloadHeader,
|
||||
nextWithdrawalIndex: st.NextWithdrawalIndex,
|
||||
nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex,
|
||||
historicalSummaries: st.HistoricalSummaries,
|
||||
depositReceiptsStartIndex: st.DepositReceiptsStartIndex,
|
||||
depositBalanceToConsume: st.DepositBalanceToConsume,
|
||||
exitBalanceToConsume: st.ExitBalanceToConsume,
|
||||
earliestExitEpoch: st.EarliestExitEpoch,
|
||||
consolidationBalanceToConsume: st.ConsolidationBalanceToConsume,
|
||||
earliestConsolidationEpoch: st.EarliestConsolidationEpoch,
|
||||
pendingBalanceDeposits: st.PendingBalanceDeposits,
|
||||
pendingPartialWithdrawals: st.PendingPartialWithdrawals,
|
||||
pendingConsolidations: st.PendingConsolidations,
|
||||
|
||||
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
|
||||
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
|
||||
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
|
||||
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
|
||||
valMapHandler: stateutil.NewValMapHandler(st.Validators),
|
||||
}
|
||||
|
||||
if features.Get().EnableExperimentalState {
|
||||
b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots)
|
||||
b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots)
|
||||
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes)
|
||||
b.balancesMultiValue = NewMultiValueBalances(st.Balances)
|
||||
b.validatorsMultiValue = NewMultiValueValidators(st.Validators)
|
||||
b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores)
|
||||
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateElectraSharedFieldRefCount)
|
||||
} else {
|
||||
bRoots := make([][32]byte, fieldparams.BlockRootsLength)
|
||||
for i, r := range st.BlockRoots {
|
||||
bRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
b.blockRoots = bRoots
|
||||
|
||||
sRoots := make([][32]byte, fieldparams.StateRootsLength)
|
||||
for i, r := range st.StateRoots {
|
||||
sRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
b.stateRoots = sRoots
|
||||
|
||||
mixes := make([][32]byte, fieldparams.RandaoMixesLength)
|
||||
for i, m := range st.RandaoMixes {
|
||||
mixes[i] = bytesutil.ToBytes32(m)
|
||||
}
|
||||
b.randaoMixes = mixes
|
||||
|
||||
b.balances = st.Balances
|
||||
b.validators = st.Validators
|
||||
b.inactivityScores = st.InactivityScores
|
||||
|
||||
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount)
|
||||
}
|
||||
|
||||
for _, f := range electraFields {
|
||||
b.dirtyFields[f] = true
|
||||
b.rebuildTrie[f] = true
|
||||
b.dirtyIndices[f] = []uint64{}
|
||||
trie, err := fieldtrie.NewFieldTrie(f, types.BasicArray, nil, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.stateFieldLeaves[f] = trie
|
||||
}
|
||||
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.LatestExecutionPayloadHeaderElectra] = stateutil.NewRef(1) // New in Electra.
|
||||
b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) // New in Capella.
|
||||
b.sharedFieldReferences[types.PendingBalanceDeposits] = stateutil.NewRef(1) // New in Electra.
|
||||
b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) // New in Electra.
|
||||
b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) // New in Electra.
|
||||
if !features.Get().EnableExperimentalState {
|
||||
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
state.Count.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Copy returns a deep copy of the beacon state.
|
||||
func (b *BeaconState) Copy() state.BeaconState {
|
||||
b.lock.RLock()
|
||||
@@ -700,17 +849,25 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
fieldCount = params.BeaconConfig().BeaconStateCapellaFieldCount
|
||||
case version.Deneb:
|
||||
fieldCount = params.BeaconConfig().BeaconStateDenebFieldCount
|
||||
case version.Electra:
|
||||
fieldCount = params.BeaconConfig().BeaconStateElectraFieldCount
|
||||
}
|
||||
|
||||
dst := &BeaconState{
|
||||
version: b.version,
|
||||
|
||||
// Primitive types, safe to copy.
|
||||
genesisTime: b.genesisTime,
|
||||
slot: b.slot,
|
||||
eth1DepositIndex: b.eth1DepositIndex,
|
||||
nextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
nextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
genesisTime: b.genesisTime,
|
||||
slot: b.slot,
|
||||
eth1DepositIndex: b.eth1DepositIndex,
|
||||
nextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
nextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
depositReceiptsStartIndex: b.depositReceiptsStartIndex,
|
||||
depositBalanceToConsume: b.depositBalanceToConsume,
|
||||
exitBalanceToConsume: b.exitBalanceToConsume,
|
||||
earliestExitEpoch: b.earliestExitEpoch,
|
||||
consolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
earliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
blockRoots: b.blockRoots,
|
||||
@@ -735,6 +892,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
currentEpochParticipation: b.currentEpochParticipation,
|
||||
inactivityScores: b.inactivityScores,
|
||||
inactivityScoresMultiValue: b.inactivityScoresMultiValue,
|
||||
pendingBalanceDeposits: b.pendingBalanceDeposits,
|
||||
pendingPartialWithdrawals: b.pendingPartialWithdrawals,
|
||||
pendingConsolidations: b.pendingConsolidations,
|
||||
|
||||
// Everything else, too small to be concerned about, constant size.
|
||||
genesisValidatorsRoot: b.genesisValidatorsRoot,
|
||||
@@ -750,6 +910,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
latestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(),
|
||||
latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapellaVal(),
|
||||
latestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDenebVal(),
|
||||
latestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectraVal(),
|
||||
|
||||
id: types.Enumerator.Inc(),
|
||||
|
||||
@@ -786,6 +947,8 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateCapellaSharedFieldRefCount)
|
||||
case version.Deneb:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateDenebSharedFieldRefCount)
|
||||
case version.Electra:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateElectraSharedFieldRefCount)
|
||||
}
|
||||
} else {
|
||||
switch b.version {
|
||||
@@ -799,6 +962,8 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount)
|
||||
case version.Deneb:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount)
|
||||
case version.Electra:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,6 +1056,10 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error {
|
||||
b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateCapellaFieldCount)
|
||||
case version.Deneb:
|
||||
b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateDenebFieldCount)
|
||||
case version.Electra:
|
||||
b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateElectraFieldCount)
|
||||
default:
|
||||
return fmt.Errorf("unknown state version (%s) when computing dirty fields in merklization", version.String(b.version))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1109,12 +1278,32 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
|
||||
return b.latestExecutionPayloadHeaderCapella.HashTreeRoot()
|
||||
case types.LatestExecutionPayloadHeaderDeneb:
|
||||
return b.latestExecutionPayloadHeaderDeneb.HashTreeRoot()
|
||||
case types.LatestExecutionPayloadHeaderElectra:
|
||||
return b.latestExecutionPayloadHeaderElectra.HashTreeRoot()
|
||||
case types.NextWithdrawalIndex:
|
||||
return ssz.Uint64Root(b.nextWithdrawalIndex), nil
|
||||
case types.NextWithdrawalValidatorIndex:
|
||||
return ssz.Uint64Root(uint64(b.nextWithdrawalValidatorIndex)), nil
|
||||
case types.HistoricalSummaries:
|
||||
return stateutil.HistoricalSummariesRoot(b.historicalSummaries)
|
||||
case types.DepositReceiptsStartIndex:
|
||||
return ssz.Uint64Root(b.depositReceiptsStartIndex), nil
|
||||
case types.DepositBalanceToConsume:
|
||||
return ssz.Uint64Root(uint64(b.depositBalanceToConsume)), nil
|
||||
case types.ExitBalanceToConsume:
|
||||
return ssz.Uint64Root(uint64(b.exitBalanceToConsume)), nil
|
||||
case types.EarliestExitEpoch:
|
||||
return ssz.Uint64Root(uint64(b.earliestExitEpoch)), nil
|
||||
case types.ConsolidationBalanceToConsume:
|
||||
return ssz.Uint64Root(uint64(b.consolidationBalanceToConsume)), nil
|
||||
case types.EarliestConsolidationEpoch:
|
||||
return ssz.Uint64Root(uint64(b.earliestConsolidationEpoch)), nil
|
||||
case types.PendingBalanceDeposits:
|
||||
return stateutil.PendingBalanceDepositsRoot(b.pendingBalanceDeposits)
|
||||
case types.PendingPartialWithdrawals:
|
||||
return stateutil.PendingPartialWithdrawalsRoot(b.pendingPartialWithdrawals)
|
||||
case types.PendingConsolidations:
|
||||
return stateutil.PendingConsolidationsRoot(b.pendingConsolidations)
|
||||
}
|
||||
return [32]byte{}, errors.New("invalid field index provided")
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
statenative "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
@@ -14,6 +16,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
)
|
||||
|
||||
func TestInitializeFromProto_Phase0(t *testing.T) {
|
||||
@@ -203,6 +206,42 @@ func TestInitializeFromProto_Deneb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitializeFromProto_Electra(t *testing.T) {
|
||||
type test struct {
|
||||
name string
|
||||
state *ethpb.BeaconStateElectra
|
||||
error string
|
||||
}
|
||||
initTests := []test{
|
||||
{
|
||||
name: "nil state",
|
||||
state: nil,
|
||||
error: "received nil state",
|
||||
},
|
||||
{
|
||||
name: "nil validators",
|
||||
state: ðpb.BeaconStateElectra{
|
||||
Slot: 4,
|
||||
Validators: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty state",
|
||||
state: ðpb.BeaconStateElectra{},
|
||||
},
|
||||
}
|
||||
for _, tt := range initTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := statenative.InitializeFromProtoElectra(tt.state)
|
||||
if tt.error != "" {
|
||||
require.ErrorContains(t, tt.error, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitializeFromProtoUnsafe_Phase0(t *testing.T) {
|
||||
testState, _ := util.DeterministicGenesisState(t, 64)
|
||||
pbState, err := statenative.ProtobufBeaconStatePhase0(testState.ToProtoUnsafe())
|
||||
@@ -365,6 +404,37 @@ func TestInitializeFromProtoUnsafe_Deneb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitializeFromProtoUnsafe_Electra(t *testing.T) {
|
||||
type test struct {
|
||||
name string
|
||||
state *ethpb.BeaconStateElectra
|
||||
error string
|
||||
}
|
||||
initTests := []test{
|
||||
{
|
||||
name: "nil validators",
|
||||
state: ðpb.BeaconStateElectra{
|
||||
Slot: 4,
|
||||
Validators: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty state",
|
||||
state: ðpb.BeaconStateElectra{},
|
||||
},
|
||||
}
|
||||
for _, tt := range initTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := statenative.InitializeFromProtoUnsafeElectra(tt.state)
|
||||
if tt.error != "" {
|
||||
assert.ErrorContains(t, tt.error, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeaconState_HashTreeRoot(t *testing.T) {
|
||||
testState, _ := util.DeterministicGenesisState(t, 64)
|
||||
|
||||
@@ -772,3 +842,29 @@ func TestBeaconState_InitializeInactivityScoresCorrectly_Deneb(t *testing.T) {
|
||||
|
||||
require.DeepSSZEqual(t, rt, newRt)
|
||||
}
|
||||
|
||||
func TestBeaconChainCopy_Electra(t *testing.T) {
|
||||
// Load a serialized Electra state from disk.
|
||||
// This is a fully hydrated random test case from spectests.
|
||||
serializedBytes, err := util.BazelFileBytes("tests/mainnet/electra/ssz_static/BeaconState/ssz_random/case_0/serialized.ssz_snappy")
|
||||
require.NoError(t, err)
|
||||
serializedSSZ, err := snappy.Decode(nil /* dst */, serializedBytes)
|
||||
require.NoError(t, err)
|
||||
pb := ðpb.BeaconStateElectra{}
|
||||
require.NoError(t, pb.UnmarshalSSZ(serializedSSZ))
|
||||
st, err := statenative.InitializeFromProtoElectra(pb)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Sanity check that InitializeFromProtoElectra and ToProto works
|
||||
if !cmp.Equal(st.ToProto(), pb, protocmp.Transform()) {
|
||||
t.Log(cmp.Diff(st.ToProto(), pb, protocmp.Transform()))
|
||||
t.Fatal("InitializeFromProtoElectra does not match input proto")
|
||||
}
|
||||
|
||||
// Perform the copy and check that the copied state matches the original state.
|
||||
st2 := st.Copy()
|
||||
if !cmp.Equal(st.ToProto(), st2.ToProto(), protocmp.Transform()) {
|
||||
t.Log(cmp.Diff(st.ToProto(), st2.ToProto(), protocmp.Transform()))
|
||||
t.Fatal("Copied state does not match original state")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
)
|
||||
@@ -83,15 +85,37 @@ func (f FieldIndex) String() string {
|
||||
case LatestExecutionPayloadHeader:
|
||||
return "latestExecutionPayloadHeader"
|
||||
case LatestExecutionPayloadHeaderCapella:
|
||||
return "LatestExecutionPayloadHeaderCapella"
|
||||
return "latestExecutionPayloadHeaderCapella"
|
||||
case LatestExecutionPayloadHeaderDeneb:
|
||||
return "latestExecutionPayloadHeaderDeneb"
|
||||
case LatestExecutionPayloadHeaderElectra:
|
||||
return "latestExecutionPayloadHeaderElectra"
|
||||
case NextWithdrawalIndex:
|
||||
return "NextWithdrawalIndex"
|
||||
return "nextWithdrawalIndex"
|
||||
case NextWithdrawalValidatorIndex:
|
||||
return "NextWithdrawalValidatorIndex"
|
||||
return "nextWithdrawalValidatorIndex"
|
||||
case HistoricalSummaries:
|
||||
return "HistoricalSummaries"
|
||||
return "historicalSummaries"
|
||||
case DepositReceiptsStartIndex:
|
||||
return "depositReceiptsStartIndex"
|
||||
case DepositBalanceToConsume:
|
||||
return "depositBalanceToConsume"
|
||||
case ExitBalanceToConsume:
|
||||
return "exitBalanceToConsume"
|
||||
case EarliestExitEpoch:
|
||||
return "earliestExitEpoch"
|
||||
case ConsolidationBalanceToConsume:
|
||||
return "consolidationBalanceToConsume"
|
||||
case EarliestConsolidationEpoch:
|
||||
return "earliestConsolidationEpoch"
|
||||
case PendingBalanceDeposits:
|
||||
return "pendingBalanceDeposits"
|
||||
case PendingPartialWithdrawals:
|
||||
return "pendingPartialWithdrawals"
|
||||
case PendingConsolidations:
|
||||
return "pendingConsolidations"
|
||||
default:
|
||||
return ""
|
||||
return fmt.Sprintf("unknown field index number: %d", f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +171,7 @@ func (f FieldIndex) RealPosition() int {
|
||||
return 22
|
||||
case NextSyncCommittee:
|
||||
return 23
|
||||
case LatestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella, LatestExecutionPayloadHeaderDeneb:
|
||||
case LatestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella, LatestExecutionPayloadHeaderDeneb, LatestExecutionPayloadHeaderElectra:
|
||||
return 24
|
||||
case NextWithdrawalIndex:
|
||||
return 25
|
||||
@@ -155,6 +179,24 @@ func (f FieldIndex) RealPosition() int {
|
||||
return 26
|
||||
case HistoricalSummaries:
|
||||
return 27
|
||||
case DepositReceiptsStartIndex:
|
||||
return 28
|
||||
case DepositBalanceToConsume:
|
||||
return 29
|
||||
case ExitBalanceToConsume:
|
||||
return 30
|
||||
case EarliestExitEpoch:
|
||||
return 31
|
||||
case ConsolidationBalanceToConsume:
|
||||
return 32
|
||||
case EarliestConsolidationEpoch:
|
||||
return 33
|
||||
case PendingBalanceDeposits:
|
||||
return 34
|
||||
case PendingPartialWithdrawals:
|
||||
return 35
|
||||
case PendingConsolidations:
|
||||
return 36
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
@@ -207,9 +249,19 @@ const (
|
||||
LatestExecutionPayloadHeader
|
||||
LatestExecutionPayloadHeaderCapella
|
||||
LatestExecutionPayloadHeaderDeneb
|
||||
LatestExecutionPayloadHeaderElectra
|
||||
NextWithdrawalIndex
|
||||
NextWithdrawalValidatorIndex
|
||||
HistoricalSummaries
|
||||
DepositReceiptsStartIndex // Electra: EIP-6110
|
||||
DepositBalanceToConsume // Electra: EIP-7251
|
||||
ExitBalanceToConsume // Electra: EIP-7251
|
||||
EarliestExitEpoch // Electra: EIP-7251
|
||||
ConsolidationBalanceToConsume // Electra: EIP-7251
|
||||
EarliestConsolidationEpoch // Electra: EIP-7251
|
||||
PendingBalanceDeposits // Electra: EIP-7251
|
||||
PendingPartialWithdrawals // Electra: EIP-7251
|
||||
PendingConsolidations // Electra: EIP-7251
|
||||
)
|
||||
|
||||
// Enumerator keeps track of the number of states created since the node's start.
|
||||
|
||||
@@ -12,7 +12,11 @@ go_library(
|
||||
"historical_summaries_root.go",
|
||||
"participation_bit_root.go",
|
||||
"pending_attestation_root.go",
|
||||
"pending_balance_deposits_root.go",
|
||||
"pending_consolidations_root.go",
|
||||
"pending_partial_withdrawals_root.go",
|
||||
"reference.go",
|
||||
"slice_root.go",
|
||||
"sync_committee.root.go",
|
||||
"trie_helpers.go",
|
||||
"unrealized_justification.go",
|
||||
|
||||
@@ -1,42 +1,10 @@
|
||||
package stateutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func HistoricalSummariesRoot(summaries []*ethpb.HistoricalSummary) ([32]byte, error) {
|
||||
max := uint64(fieldparams.HistoricalRootsLength)
|
||||
if uint64(len(summaries)) > max {
|
||||
return [32]byte{}, fmt.Errorf("historical summary exceeds max length %d", max)
|
||||
}
|
||||
|
||||
roots := make([][32]byte, len(summaries))
|
||||
for i := 0; i < len(summaries); i++ {
|
||||
r, err := summaries[i].HashTreeRoot()
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not merkleize historical summary")
|
||||
}
|
||||
roots[i] = r
|
||||
}
|
||||
|
||||
summariesRoot, err := ssz.BitwiseMerkleize(roots, uint64(len(roots)), fieldparams.HistoricalRootsLength)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute historical summaries merkleization")
|
||||
}
|
||||
summariesLenBuf := new(bytes.Buffer)
|
||||
if err := binary.Write(summariesLenBuf, binary.LittleEndian, uint64(len(summaries))); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not marshal historical summary length")
|
||||
}
|
||||
// We need to mix in the length of the slice.
|
||||
summariesLenRoot := make([]byte, 32)
|
||||
copy(summariesLenRoot, summariesLenBuf.Bytes())
|
||||
res := ssz.MixInLength(summariesRoot, summariesLenRoot)
|
||||
return res, nil
|
||||
return SliceRoot(summaries, fieldparams.HistoricalRootsLength)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package stateutil
|
||||
|
||||
import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func PendingBalanceDepositsRoot(slice []*ethpb.PendingBalanceDeposit) ([32]byte, error) {
|
||||
return SliceRoot(slice, fieldparams.PendingBalanceDepositsLimit)
|
||||
}
|
||||
10
beacon-chain/state/stateutil/pending_consolidations_root.go
Normal file
10
beacon-chain/state/stateutil/pending_consolidations_root.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package stateutil
|
||||
|
||||
import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func PendingConsolidationsRoot(slice []*ethpb.PendingConsolidation) ([32]byte, error) {
|
||||
return SliceRoot(slice, fieldparams.PendingConsolidationsLimit)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package stateutil
|
||||
|
||||
import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func PendingPartialWithdrawalsRoot(slice []*ethpb.PendingPartialWithdrawal) ([32]byte, error) {
|
||||
return SliceRoot(slice, fieldparams.PendingPartialWithdrawalsLimit)
|
||||
}
|
||||
41
beacon-chain/state/stateutil/slice_root.go
Normal file
41
beacon-chain/state/stateutil/slice_root.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package stateutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
)
|
||||
|
||||
// SliceRoot computes the root of a slice of hashable objects.
|
||||
func SliceRoot[T ssz.Hashable](slice []T, limit uint64) ([32]byte, error) {
|
||||
max := limit
|
||||
if uint64(len(slice)) > max {
|
||||
return [32]byte{}, fmt.Errorf("slice exceeds max length %d", max)
|
||||
}
|
||||
|
||||
roots := make([][32]byte, len(slice))
|
||||
for i := 0; i < len(slice); i++ {
|
||||
r, err := slice[i].HashTreeRoot()
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not merkleize object")
|
||||
}
|
||||
roots[i] = r
|
||||
}
|
||||
|
||||
sliceRoot, err := ssz.BitwiseMerkleize(roots, uint64(len(roots)), limit)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not slice merkleization")
|
||||
}
|
||||
sliceLenBuf := new(bytes.Buffer)
|
||||
if err := binary.Write(sliceLenBuf, binary.LittleEndian, uint64(len(slice))); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not marshal slice length")
|
||||
}
|
||||
// We need to mix in the length of the slice.
|
||||
sliceLenRoot := make([]byte, 32)
|
||||
copy(sliceLenRoot, sliceLenBuf.Bytes())
|
||||
res := ssz.MixInLength(sliceRoot, sliceLenRoot)
|
||||
return res, nil
|
||||
}
|
||||
@@ -250,11 +250,11 @@ func AddInMixin(root [32]byte, length uint64) ([32]byte, error) {
|
||||
|
||||
// Merkleize 32-byte leaves into a Merkle trie for its adequate depth, returning
|
||||
// the resulting layers of the trie based on the appropriate depth. This function
|
||||
// pads the leaves to a length of 32.
|
||||
// pads the leaves to a length of a multiple of 32.
|
||||
func Merkleize(leaves [][]byte) [][][]byte {
|
||||
hashFunc := hash.CustomSHA256Hasher()
|
||||
layers := make([][][]byte, ssz.Depth(uint64(len(leaves)))+1)
|
||||
for len(leaves) != 32 {
|
||||
for len(leaves)%32 != 0 {
|
||||
leaves = append(leaves, make([]byte, 32))
|
||||
}
|
||||
currentLayer := leaves
|
||||
|
||||
@@ -236,20 +236,20 @@ type BeaconChainConfig struct {
|
||||
MaxRequestBlocksDeneb uint64 `yaml:"MAX_REQUEST_BLOCKS_DENEB" spec:"true"` // MaxRequestBlocksDeneb is the maximum number of blocks in a single request after the deneb epoch.
|
||||
|
||||
// Values introduce in Electra upgrade
|
||||
DataColumnSidecarSubnetCount uint64 `yaml:"DATA_COLUMN_SIDECAR_SUBNET_COUNT" spec:"true"` // DataColumnSidecarSubnetCount is the number of data column sidecar subnets used in the gossipsub protocol
|
||||
MaxPerEpochActivationExitChurnLimit uint64 `yaml:"MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT" spec:"true"` // MaxPerEpochActivationExitChurnLimit represents the maximum combined activation and exit churn.
|
||||
MinPerEpochChurnLimitElectra uint64 `yaml:"MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA" spec:"true"` // MinPerEpochChurnLimitElectra is the minimum amount of churn allotted for validator rotations for electra.
|
||||
MaxRequestDataColumnSidecars uint64 `yaml:"MAX_REQUEST_DATA_COLUMN_SIDECARS" spec:"true"` // MaxRequestDataColumnSidecars is the maximum number of data column sidecars in a single request
|
||||
MaxEffectiveBalanceElectra uint64 `yaml:"MAX_EFFECTIVE_BALANCE_ELECTRA" spec:"true"` // MaxEffectiveBalanceElectra is the maximal amount of Gwei that is effective for staking, increased in electra.
|
||||
MinSlashingPenaltyQuotientElectra uint64 `yaml:"MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA" spec:"true"` // MinSlashingPenaltyQuotientElectra is used to calculate the minimum penalty to prevent DoS attacks, modified for electra.
|
||||
WhistleBlowerRewardQuotientElectra uint64 `yaml:"WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA" spec:"true"` // WhistleBlowerRewardQuotientElectra is used to calculate whistle blower reward, modified in electra.
|
||||
PendingBalanceDepositLimit uint64 `yaml:"PENDING_BALANCE_DEPOSITS_LIMIT" spec:"true"` // PendingBalanceDepositLimit is the maximum number of pending balance deposits allowed in the beacon state.
|
||||
PendingPartialWithdrawalsLimit uint64 `yaml:"PENDING_PARTIAL_WITHDRAWALS_LIMIT" spec:"true"` // PendingPartialWithdrawalsLimit is the maximum number of pending partial withdrawals allowed in the beacon state.
|
||||
PendingConsolidationsLimit uint64 `yaml:"PENDING_CONSOLIDATIONS_LIMIT" spec:"true"` // PendingConsolidationsLimit is the maximum number of pending validator consolidations allowed in the beacon state.
|
||||
MaxConsolidations uint64 `yaml:"MAX_CONSOLIDATIONS" spec:"true"` // MaxConsolidations is the maximum number of consolidations in a block.
|
||||
MaxPendingPartialsPerWithdrawalSweep uint64 `yaml:"MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP" spec:"true"` // MaxPendingPartialsPerWithdrawalSweep is the maximum number of pending partial withdrawals to process per payload.
|
||||
FullExitRequestAmount uint64 `yaml:"FULL_EXIT_REQUEST_AMOUNT" spec:"true"` // FullExitRequestAmount is the amount of Gwei required to request a full exit.
|
||||
MaxWithdrawalRequestsPerPayload uint64 `yaml:"MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD" spec:"true"` // MaxWithdrawalRequestsPerPayload is the maximum number of execution layer withdrawal requests in each payload.
|
||||
DataColumnSidecarSubnetCount uint64 `yaml:"DATA_COLUMN_SIDECAR_SUBNET_COUNT" spec:"true"` // DataColumnSidecarSubnetCount is the number of data column sidecar subnets used in the gossipsub protocol
|
||||
MaxPerEpochActivationExitChurnLimit uint64 `yaml:"MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT" spec:"true"` // MaxPerEpochActivationExitChurnLimit represents the maximum combined activation and exit churn.
|
||||
MinPerEpochChurnLimitElectra uint64 `yaml:"MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA" spec:"true"` // MinPerEpochChurnLimitElectra is the minimum amount of churn allotted for validator rotations for electra.
|
||||
MaxRequestDataColumnSidecars uint64 `yaml:"MAX_REQUEST_DATA_COLUMN_SIDECARS" spec:"true"` // MaxRequestDataColumnSidecars is the maximum number of data column sidecars in a single request
|
||||
MaxEffectiveBalanceElectra uint64 `yaml:"MAX_EFFECTIVE_BALANCE_ELECTRA" spec:"true"` // MaxEffectiveBalanceElectra is the maximal amount of Gwei that is effective for staking, increased in electra.
|
||||
MinSlashingPenaltyQuotientElectra uint64 `yaml:"MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA" spec:"true"` // MinSlashingPenaltyQuotientElectra is used to calculate the minimum penalty to prevent DoS attacks, modified for electra.
|
||||
WhistleBlowerRewardQuotientElectra uint64 `yaml:"WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA" spec:"true"` // WhistleBlowerRewardQuotientElectra is used to calculate whistle blower reward, modified in electra.
|
||||
PendingBalanceDepositLimit uint64 `yaml:"PENDING_BALANCE_DEPOSITS_LIMIT" spec:"true"` // PendingBalanceDepositLimit is the maximum number of pending balance deposits allowed in the beacon state.
|
||||
PendingPartialWithdrawalsLimit uint64 `yaml:"PENDING_PARTIAL_WITHDRAWALS_LIMIT" spec:"true"` // PendingPartialWithdrawalsLimit is the maximum number of pending partial withdrawals allowed in the beacon state.
|
||||
PendingConsolidationsLimit uint64 `yaml:"PENDING_CONSOLIDATIONS_LIMIT" spec:"true"` // PendingConsolidationsLimit is the maximum number of pending validator consolidations allowed in the beacon state.
|
||||
MaxConsolidations uint64 `yaml:"MAX_CONSOLIDATIONS" spec:"true"` // MaxConsolidations is the maximum number of consolidations in a block.
|
||||
MaxPendingPartialsPerWithdrawalsSweep uint64 `yaml:"MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP" spec:"true"` // MaxPendingPartialsPerWithdrawalsSweep is the maximum number of pending partial withdrawals to process per payload.
|
||||
FullExitRequestAmount uint64 `yaml:"FULL_EXIT_REQUEST_AMOUNT" spec:"true"` // FullExitRequestAmount is the amount of Gwei required to request a full exit.
|
||||
MaxWithdrawalRequestsPerPayload uint64 `yaml:"MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD" spec:"true"` // MaxWithdrawalRequestsPerPayload is the maximum number of execution layer withdrawal requests in each payload.
|
||||
|
||||
// Networking Specific Parameters
|
||||
GossipMaxSize uint64 `yaml:"GOSSIP_MAX_SIZE" spec:"true"` // GossipMaxSize is the maximum allowed size of uncompressed gossip messages.
|
||||
@@ -288,6 +288,7 @@ func configForkSchedule(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt
|
||||
fvs[bytesutil.ToBytes4(b.BellatrixForkVersion)] = b.BellatrixForkEpoch
|
||||
fvs[bytesutil.ToBytes4(b.CapellaForkVersion)] = b.CapellaForkEpoch
|
||||
fvs[bytesutil.ToBytes4(b.DenebForkVersion)] = b.DenebForkEpoch
|
||||
fvs[bytesutil.ToBytes4(b.ElectraForkVersion)] = b.ElectraForkEpoch
|
||||
return fvs
|
||||
}
|
||||
|
||||
@@ -309,6 +310,7 @@ func ConfigForkVersions(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt
|
||||
bytesutil.ToBytes4(b.BellatrixForkVersion): version.Bellatrix,
|
||||
bytesutil.ToBytes4(b.CapellaForkVersion): version.Capella,
|
||||
bytesutil.ToBytes4(b.DenebForkVersion): version.Deneb,
|
||||
bytesutil.ToBytes4(b.ElectraForkVersion): version.Electra,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ func InteropConfig() *BeaconChainConfig {
|
||||
c.BellatrixForkVersion = []byte{2, 0, 0, 235}
|
||||
c.CapellaForkVersion = []byte{3, 0, 0, 235}
|
||||
c.DenebForkVersion = []byte{4, 0, 0, 235}
|
||||
c.ElectraForkVersion = []byte{5, 0, 0, 235}
|
||||
|
||||
c.InitializeForkSchedule()
|
||||
return c
|
||||
|
||||
@@ -214,6 +214,8 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte {
|
||||
fmt.Sprintf("BLOB_SIDECAR_SUBNET_COUNT: %d", cfg.BlobsidecarSubnetCount),
|
||||
fmt.Sprintf("DENEB_FORK_EPOCH: %d", cfg.DenebForkEpoch),
|
||||
fmt.Sprintf("DENEB_FORK_VERSION: %#x", cfg.DenebForkVersion),
|
||||
fmt.Sprintf("ELECTRA_FORK_EPOCH: %d", cfg.ElectraForkEpoch),
|
||||
fmt.Sprintf("ELECTRA_FORK_VERSION: %#x", cfg.ElectraForkVersion),
|
||||
fmt.Sprintf("EPOCHS_PER_SUBNET_SUBSCRIPTION: %d", cfg.EpochsPerSubnetSubscription),
|
||||
fmt.Sprintf("ATTESTATION_SUBNET_EXTRA_BITS: %d", cfg.AttestationSubnetExtraBits),
|
||||
fmt.Sprintf("ATTESTATION_SUBNET_PREFIX_BITS: %d", cfg.AttestationSubnetPrefixBits),
|
||||
|
||||
@@ -275,21 +275,21 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
MaxRequestBlocksDeneb: 128,
|
||||
|
||||
// Values related to electra
|
||||
MaxRequestDataColumnSidecars: 16384,
|
||||
DataColumnSidecarSubnetCount: 32,
|
||||
MinPerEpochChurnLimitElectra: 128_000_000_000,
|
||||
MaxPerEpochActivationExitChurnLimit: 256_000_000_000,
|
||||
MaxEffectiveBalanceElectra: 2048_000_000_000,
|
||||
MinSlashingPenaltyQuotientElectra: 4096,
|
||||
WhistleBlowerRewardQuotientElectra: 4096,
|
||||
PendingBalanceDepositLimit: 134_217_728,
|
||||
PendingPartialWithdrawalsLimit: 134_217_728,
|
||||
PendingConsolidationsLimit: 262_144,
|
||||
MinActivationBalance: 32_000_000_000,
|
||||
MaxConsolidations: 1,
|
||||
MaxPendingPartialsPerWithdrawalSweep: 8,
|
||||
FullExitRequestAmount: 0,
|
||||
MaxWithdrawalRequestsPerPayload: 16,
|
||||
MaxRequestDataColumnSidecars: 16384,
|
||||
DataColumnSidecarSubnetCount: 32,
|
||||
MinPerEpochChurnLimitElectra: 128_000_000_000,
|
||||
MaxPerEpochActivationExitChurnLimit: 256_000_000_000,
|
||||
MaxEffectiveBalanceElectra: 2048_000_000_000,
|
||||
MinSlashingPenaltyQuotientElectra: 4096,
|
||||
WhistleBlowerRewardQuotientElectra: 4096,
|
||||
PendingBalanceDepositLimit: 134_217_728,
|
||||
PendingPartialWithdrawalsLimit: 134_217_728,
|
||||
PendingConsolidationsLimit: 262_144,
|
||||
MinActivationBalance: 32_000_000_000,
|
||||
MaxConsolidations: 1,
|
||||
MaxPendingPartialsPerWithdrawalsSweep: 8,
|
||||
FullExitRequestAmount: 0,
|
||||
MaxWithdrawalRequestsPerPayload: 16,
|
||||
|
||||
// Values related to networking parameters.
|
||||
GossipMaxSize: 10 * 1 << 20, // 10 MiB
|
||||
@@ -332,16 +332,19 @@ func FillTestVersions(c *BeaconChainConfig, b byte) {
|
||||
c.BellatrixForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
c.CapellaForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
c.DenebForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
c.ElectraForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
|
||||
c.GenesisForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.AltairForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.BellatrixForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.CapellaForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.DenebForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.ElectraForkVersion[fieldparams.VersionLength-1] = b
|
||||
|
||||
c.GenesisForkVersion[0] = 0
|
||||
c.AltairForkVersion[0] = 1
|
||||
c.BellatrixForkVersion[0] = 2
|
||||
c.CapellaForkVersion[0] = 3
|
||||
c.DenebForkVersion[0] = 4
|
||||
c.ElectraForkVersion[0] = 5
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ func MinimalSpecConfig() *BeaconChainConfig {
|
||||
minimalConfig.MaxPartialWithdrawalsPerPayload = 1
|
||||
minimalConfig.MaxWithdrawalRequestsPerPayload = 2
|
||||
minimalConfig.PendingPartialWithdrawalsLimit = 64
|
||||
minimalConfig.MaxPendingPartialsPerWithdrawalSweep = 1
|
||||
minimalConfig.MaxPendingPartialsPerWithdrawalsSweep = 1
|
||||
|
||||
// Ethereum PoW parameters.
|
||||
minimalConfig.DepositChainID = 5 // Chain ID of eth1 goerli.
|
||||
|
||||
3
config/params/testdata/e2e_config.yaml
vendored
3
config/params/testdata/e2e_config.yaml
vendored
@@ -44,6 +44,9 @@ CAPELLA_FORK_EPOCH: 10
|
||||
# Deneb
|
||||
DENEB_FORK_VERSION: 0x040000fd
|
||||
DENEB_FORK_EPOCH: 12
|
||||
# Electra
|
||||
ELECTRA_FORK_VERSION: 0x050000fd
|
||||
ELECTRA_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Time parameters
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package params
|
||||
|
||||
import "math"
|
||||
|
||||
const (
|
||||
AltairE2EForkEpoch = 6
|
||||
BellatrixE2EForkEpoch = 8
|
||||
CapellaE2EForkEpoch = 10
|
||||
DenebE2EForkEpoch = 12
|
||||
ElectraE2EForkEpoch = math.MaxUint64
|
||||
)
|
||||
|
||||
// E2ETestConfig retrieves the configurations made specifically for E2E testing.
|
||||
@@ -40,6 +43,7 @@ func E2ETestConfig() *BeaconChainConfig {
|
||||
e2eConfig.BellatrixForkEpoch = BellatrixE2EForkEpoch
|
||||
e2eConfig.CapellaForkEpoch = CapellaE2EForkEpoch
|
||||
e2eConfig.DenebForkEpoch = DenebE2EForkEpoch
|
||||
e2eConfig.ElectraForkEpoch = ElectraE2EForkEpoch
|
||||
|
||||
// Terminal Total Difficulty.
|
||||
e2eConfig.TerminalTotalDifficulty = "480"
|
||||
@@ -51,6 +55,7 @@ func E2ETestConfig() *BeaconChainConfig {
|
||||
e2eConfig.BellatrixForkVersion = []byte{2, 0, 0, 253}
|
||||
e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 253}
|
||||
e2eConfig.DenebForkVersion = []byte{4, 0, 0, 253}
|
||||
e2eConfig.ElectraForkVersion = []byte{5, 0, 0, 253}
|
||||
|
||||
e2eConfig.InitializeForkSchedule()
|
||||
return e2eConfig
|
||||
@@ -82,6 +87,7 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
|
||||
e2eConfig.BellatrixForkEpoch = BellatrixE2EForkEpoch
|
||||
e2eConfig.CapellaForkEpoch = CapellaE2EForkEpoch
|
||||
e2eConfig.DenebForkEpoch = DenebE2EForkEpoch
|
||||
e2eConfig.ElectraForkEpoch = ElectraE2EForkEpoch
|
||||
|
||||
// Terminal Total Difficulty.
|
||||
e2eConfig.TerminalTotalDifficulty = "480"
|
||||
@@ -93,6 +99,7 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
|
||||
e2eConfig.BellatrixForkVersion = []byte{2, 0, 0, 254}
|
||||
e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 254}
|
||||
e2eConfig.DenebForkVersion = []byte{4, 0, 0, 254}
|
||||
e2eConfig.ElectraForkVersion = []byte{5, 0, 0, 254}
|
||||
|
||||
// Deneb changes.
|
||||
e2eConfig.MinPerEpochChurnLimit = 2
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package params
|
||||
|
||||
import "math"
|
||||
|
||||
// UseHoleskyNetworkConfig uses the Holesky beacon chain specific network config.
|
||||
func UseHoleskyNetworkConfig() {
|
||||
cfg := BeaconNetworkConfig().Copy()
|
||||
@@ -36,6 +38,8 @@ func HoleskyConfig() *BeaconChainConfig {
|
||||
cfg.CapellaForkVersion = []byte{0x4, 0x1, 0x70, 0x0}
|
||||
cfg.DenebForkEpoch = 29696
|
||||
cfg.DenebForkVersion = []byte{0x05, 0x1, 0x70, 0x0}
|
||||
cfg.ElectraForkEpoch = math.MaxUint64
|
||||
cfg.ElectraForkVersion = []byte{0x06, 0x1, 0x70, 0x0} // TODO: Define holesky fork version for electra. This is a placeholder value.
|
||||
cfg.TerminalTotalDifficulty = "0"
|
||||
cfg.DepositContractAddress = "0x4242424242424242424242424242424242424242"
|
||||
cfg.EjectionBalance = 28000000000
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
eth1Params "github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
@@ -37,6 +39,8 @@ func SepoliaConfig() *BeaconChainConfig {
|
||||
cfg.CapellaForkVersion = []byte{0x90, 0x00, 0x00, 0x72}
|
||||
cfg.DenebForkEpoch = 132608
|
||||
cfg.DenebForkVersion = []byte{0x90, 0x00, 0x00, 0x73}
|
||||
cfg.ElectraForkEpoch = math.MaxUint64
|
||||
cfg.ElectraForkVersion = []byte{0x90, 0x00, 0x00, 0x74} // TODO: Define sepolia fork version for electra. This is a placeholder value.
|
||||
cfg.TerminalTotalDifficulty = "17000000000000000"
|
||||
cfg.DepositContractAddress = "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D"
|
||||
cfg.InitializeForkSchedule()
|
||||
|
||||
@@ -87,6 +87,8 @@ func FromForkVersion(cv [fieldparams.VersionLength]byte) (*VersionedUnmarshaler,
|
||||
fork = version.Capella
|
||||
case bytesutil.ToBytes4(cfg.DenebForkVersion):
|
||||
fork = version.Deneb
|
||||
case bytesutil.ToBytes4(cfg.ElectraForkVersion):
|
||||
fork = version.Electra
|
||||
default:
|
||||
return nil, errors.Wrapf(ErrForkNotFound, "version=%#x", cv)
|
||||
}
|
||||
@@ -152,6 +154,16 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconState(marshaled []byte) (s state.
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName)
|
||||
}
|
||||
case version.Electra:
|
||||
st := ðpb.BeaconStateElectra{}
|
||||
err = st.UnmarshalSSZ(marshaled)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal state, detected fork=%s", forkName)
|
||||
}
|
||||
s, err = state_native.InitializeFromProtoUnsafeElectra(st)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unable to initialize BeaconState for fork version=%s", forkName)
|
||||
}
|
||||
@@ -200,6 +212,8 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac
|
||||
blk = ðpb.SignedBeaconBlockCapella{}
|
||||
case version.Deneb:
|
||||
blk = ðpb.SignedBeaconBlockDeneb{}
|
||||
case version.Electra:
|
||||
blk = ðpb.SignedBeaconBlockElectra{}
|
||||
default:
|
||||
forkName := version.String(cf.Fork)
|
||||
return nil, fmt.Errorf("unable to initialize ReadOnlyBeaconBlock for fork version=%s at slot=%d", forkName, slot)
|
||||
@@ -235,6 +249,8 @@ func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (i
|
||||
blk = ðpb.SignedBlindedBeaconBlockCapella{}
|
||||
case version.Deneb:
|
||||
blk = ðpb.SignedBlindedBeaconBlockDeneb{}
|
||||
case version.Electra:
|
||||
blk = ðpb.SignedBlindedBeaconBlockElectra{}
|
||||
default:
|
||||
forkName := version.String(cf.Fork)
|
||||
return nil, fmt.Errorf("unable to initialize ReadOnlyBeaconBlock for fork version=%s at slot=%d", forkName, slot)
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestSlotFromBlock(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestByState(t *testing.T) {
|
||||
undo := util.HackDenebMaxuint(t)
|
||||
undo := util.HackElectraMaxuint(t)
|
||||
defer undo()
|
||||
bc := params.BeaconConfig()
|
||||
altairSlot, err := slots.EpochStart(bc.AltairForkEpoch)
|
||||
@@ -58,6 +58,8 @@ func TestByState(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
denebSlot, err := slots.EpochStart(bc.DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
electraSlot, err := slots.EpochStart(bc.ElectraForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
name string
|
||||
version int
|
||||
@@ -94,6 +96,12 @@ func TestByState(t *testing.T) {
|
||||
slot: denebSlot,
|
||||
forkversion: bytesutil.ToBytes4(bc.DenebForkVersion),
|
||||
},
|
||||
{
|
||||
name: "electra",
|
||||
version: version.Electra,
|
||||
slot: electraSlot,
|
||||
forkversion: bytesutil.ToBytes4(bc.ElectraForkVersion),
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
st, err := stateForVersion(c.version)
|
||||
@@ -126,6 +134,8 @@ func stateForVersion(v int) (state.BeaconState, error) {
|
||||
return util.NewBeaconStateCapella()
|
||||
case version.Deneb:
|
||||
return util.NewBeaconStateDeneb()
|
||||
case version.Electra:
|
||||
return util.NewBeaconStateElectra()
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized version %d", v)
|
||||
}
|
||||
@@ -133,7 +143,7 @@ func stateForVersion(v int) (state.BeaconState, error) {
|
||||
|
||||
func TestUnmarshalState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
undo := util.HackDenebMaxuint(t)
|
||||
undo := util.HackElectraMaxuint(t)
|
||||
defer undo()
|
||||
bc := params.BeaconConfig()
|
||||
altairSlot, err := slots.EpochStart(bc.AltairForkEpoch)
|
||||
@@ -144,6 +154,8 @@ func TestUnmarshalState(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
denebSlot, err := slots.EpochStart(bc.DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
electraSlot, err := slots.EpochStart(bc.ElectraForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
name string
|
||||
version int
|
||||
@@ -180,6 +192,12 @@ func TestUnmarshalState(t *testing.T) {
|
||||
slot: denebSlot,
|
||||
forkversion: bytesutil.ToBytes4(bc.DenebForkVersion),
|
||||
},
|
||||
{
|
||||
name: "electra",
|
||||
version: version.Electra,
|
||||
slot: electraSlot,
|
||||
forkversion: bytesutil.ToBytes4(bc.ElectraForkVersion),
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
st, err := stateForVersion(c.version)
|
||||
@@ -205,7 +223,7 @@ func TestUnmarshalState(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDetectAndUnmarshalBlock(t *testing.T) {
|
||||
undo := util.HackDenebMaxuint(t)
|
||||
undo := util.HackElectraMaxuint(t)
|
||||
defer undo()
|
||||
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
||||
require.NoError(t, err)
|
||||
@@ -215,6 +233,8 @@ func TestDetectAndUnmarshalBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
denebS, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock
|
||||
name string
|
||||
@@ -260,6 +280,11 @@ func TestDetectAndUnmarshalBlock(t *testing.T) {
|
||||
b: signedTestBlockDeneb,
|
||||
slot: denebS,
|
||||
},
|
||||
{
|
||||
name: "first slot of electra",
|
||||
b: signedTestBlockElectra,
|
||||
slot: electraS,
|
||||
},
|
||||
{
|
||||
name: "bellatrix block in altair slot",
|
||||
b: signedTestBlockBellatrix,
|
||||
@@ -296,13 +321,14 @@ func TestDetectAndUnmarshalBlock(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnmarshalBlock(t *testing.T) {
|
||||
undo := util.HackDenebMaxuint(t)
|
||||
undo := util.HackElectraMaxuint(t)
|
||||
defer undo()
|
||||
genv := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion)
|
||||
altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion)
|
||||
bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion)
|
||||
capellaV := bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion)
|
||||
denebV := bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion)
|
||||
electraV := bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion)
|
||||
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
||||
require.NoError(t, err)
|
||||
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
||||
@@ -311,6 +337,8 @@ func TestUnmarshalBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
denebS, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock
|
||||
name string
|
||||
@@ -365,6 +393,12 @@ func TestUnmarshalBlock(t *testing.T) {
|
||||
version: denebV,
|
||||
slot: denebS,
|
||||
},
|
||||
{
|
||||
name: "first slot of electra",
|
||||
b: signedTestBlockElectra,
|
||||
version: electraV,
|
||||
slot: electraS,
|
||||
},
|
||||
{
|
||||
name: "bellatrix block in altair slot",
|
||||
b: signedTestBlockBellatrix,
|
||||
@@ -409,13 +443,14 @@ func TestUnmarshalBlock(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnmarshalBlindedBlock(t *testing.T) {
|
||||
undo := util.HackDenebMaxuint(t)
|
||||
undo := util.HackElectraMaxuint(t)
|
||||
defer undo()
|
||||
genv := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion)
|
||||
altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion)
|
||||
bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion)
|
||||
capellaV := bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion)
|
||||
denebV := bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion)
|
||||
electraV := bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion)
|
||||
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
||||
require.NoError(t, err)
|
||||
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
||||
@@ -424,6 +459,8 @@ func TestUnmarshalBlindedBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
denebS, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock
|
||||
name string
|
||||
@@ -485,6 +522,12 @@ func TestUnmarshalBlindedBlock(t *testing.T) {
|
||||
version: denebV,
|
||||
slot: denebS,
|
||||
},
|
||||
{
|
||||
name: "first slot of electra",
|
||||
b: signedTestBlindedBlockElectra,
|
||||
version: electraV,
|
||||
slot: electraS,
|
||||
},
|
||||
{
|
||||
name: "genesis block in altair slot",
|
||||
b: signedTestBlockGenesis,
|
||||
@@ -577,6 +620,14 @@ func signedTestBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnl
|
||||
return s
|
||||
}
|
||||
|
||||
func signedTestBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
||||
b := util.NewBeaconBlockElectra()
|
||||
b.Block.Slot = slot
|
||||
s, err := blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
return s
|
||||
}
|
||||
|
||||
func signedTestBlindedBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
||||
b := util.NewBlindedBeaconBlockDeneb()
|
||||
b.Message.Slot = slot
|
||||
@@ -584,3 +635,11 @@ func signedTestBlindedBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.
|
||||
require.NoError(t, err)
|
||||
return s
|
||||
}
|
||||
|
||||
func signedTestBlindedBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
||||
b := util.NewBlindedBeaconBlockElectra()
|
||||
b.Message.Slot = slot
|
||||
s, err := blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ go_library(
|
||||
srcs = ["math_helper.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/math",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@com_github_thomaso_mirodin_intmath//u64:go_default_library"],
|
||||
deps = [
|
||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||
"@com_github_thomaso_mirodin_intmath//u64:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
|
||||
@@ -3,11 +3,13 @@ package math
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
stdmath "math"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
"sync"
|
||||
|
||||
fssz "github.com/prysmaticlabs/fastssz"
|
||||
"github.com/thomaso-mirodin/intmath/u64"
|
||||
)
|
||||
|
||||
@@ -216,9 +218,53 @@ func AddInt(i ...int) (int, error) {
|
||||
// Wei is the smallest unit of Ether, represented as a pointer to a bigInt.
|
||||
type Wei *big.Int
|
||||
|
||||
var _ fssz.HashRoot = (Gwei)(0)
|
||||
var _ fssz.Marshaler = (*Gwei)(nil)
|
||||
var _ fssz.Unmarshaler = (*Gwei)(nil)
|
||||
|
||||
// Gwei is a denomination of 1e9 Wei represented as an uint64.
|
||||
type Gwei uint64
|
||||
|
||||
// HashTreeRoot --
|
||||
func (g Gwei) HashTreeRoot() ([32]byte, error) {
|
||||
return fssz.HashWithDefaultHasher(g)
|
||||
}
|
||||
|
||||
// HashTreeRootWith --
|
||||
func (g Gwei) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
hh.PutUint64(uint64(g))
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalSSZ --
|
||||
func (g *Gwei) UnmarshalSSZ(buf []byte) error {
|
||||
if len(buf) != g.SizeSSZ() {
|
||||
return fmt.Errorf("expected buffer of length %d received %d", g.SizeSSZ(), len(buf))
|
||||
}
|
||||
*g = Gwei(fssz.UnmarshallUint64(buf))
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalSSZTo --
|
||||
func (g *Gwei) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
marshalled, err := g.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(dst, marshalled...), nil
|
||||
}
|
||||
|
||||
// MarshalSSZ --
|
||||
func (g *Gwei) MarshalSSZ() ([]byte, error) {
|
||||
marshalled := fssz.MarshalUint64([]byte{}, uint64(*g))
|
||||
return marshalled, nil
|
||||
}
|
||||
|
||||
// SizeSSZ --
|
||||
func (g *Gwei) SizeSSZ() int {
|
||||
return 8
|
||||
}
|
||||
|
||||
// WeiToGwei converts big int wei to uint64 gwei.
|
||||
// The input `v` is copied before being modified.
|
||||
func WeiToGwei(v Wei) Gwei {
|
||||
|
||||
@@ -51,6 +51,7 @@ ssz_gen_marshal(
|
||||
includes = [
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//math:go_default_library",
|
||||
],
|
||||
objs = [
|
||||
"BeaconBlockAltair",
|
||||
@@ -162,6 +163,7 @@ go_proto_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/ext:go_default_library",
|
||||
"@com_github_golang_protobuf//proto:go_default_library",
|
||||
@@ -219,6 +221,7 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = SSZ_DEPS + [
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/ext:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
|
||||
178
proto/prysm/v1alpha1/beacon_state.pb.go
generated
178
proto/prysm/v1alpha1/beacon_state.pb.go
generated
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
|
||||
github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
github_com_prysmaticlabs_prysm_v5_math "github.com/prysmaticlabs/prysm/v5/math"
|
||||
v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
_ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
@@ -1868,10 +1869,10 @@ type BeaconStateElectra struct {
|
||||
NextWithdrawalValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,11002,opt,name=next_withdrawal_validator_index,json=nextWithdrawalValidatorIndex,proto3" json:"next_withdrawal_validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"`
|
||||
HistoricalSummaries []*HistoricalSummary `protobuf:"bytes,11003,rep,name=historical_summaries,json=historicalSummaries,proto3" json:"historical_summaries,omitempty" ssz-max:"16777216"`
|
||||
DepositReceiptsStartIndex uint64 `protobuf:"varint,12001,opt,name=deposit_receipts_start_index,json=depositReceiptsStartIndex,proto3" json:"deposit_receipts_start_index,omitempty"`
|
||||
DepositBalanceToConsume uint64 `protobuf:"varint,12002,opt,name=deposit_balance_to_consume,json=depositBalanceToConsume,proto3" json:"deposit_balance_to_consume,omitempty"`
|
||||
ExitBalanceToConsume uint64 `protobuf:"varint,12003,opt,name=exit_balance_to_consume,json=exitBalanceToConsume,proto3" json:"exit_balance_to_consume,omitempty"`
|
||||
DepositBalanceToConsume github_com_prysmaticlabs_prysm_v5_math.Gwei `protobuf:"varint,12002,opt,name=deposit_balance_to_consume,json=depositBalanceToConsume,proto3" json:"deposit_balance_to_consume,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/math.Gwei"`
|
||||
ExitBalanceToConsume github_com_prysmaticlabs_prysm_v5_math.Gwei `protobuf:"varint,12003,opt,name=exit_balance_to_consume,json=exitBalanceToConsume,proto3" json:"exit_balance_to_consume,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/math.Gwei"`
|
||||
EarliestExitEpoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,12004,opt,name=earliest_exit_epoch,json=earliestExitEpoch,proto3" json:"earliest_exit_epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"`
|
||||
ConsolidationBalanceToConsume uint64 `protobuf:"varint,12005,opt,name=consolidation_balance_to_consume,json=consolidationBalanceToConsume,proto3" json:"consolidation_balance_to_consume,omitempty"`
|
||||
ConsolidationBalanceToConsume github_com_prysmaticlabs_prysm_v5_math.Gwei `protobuf:"varint,12005,opt,name=consolidation_balance_to_consume,json=consolidationBalanceToConsume,proto3" json:"consolidation_balance_to_consume,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/math.Gwei"`
|
||||
EarliestConsolidationEpoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,12006,opt,name=earliest_consolidation_epoch,json=earliestConsolidationEpoch,proto3" json:"earliest_consolidation_epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"`
|
||||
PendingBalanceDeposits []*PendingBalanceDeposit `protobuf:"bytes,12007,rep,name=pending_balance_deposits,json=pendingBalanceDeposits,proto3" json:"pending_balance_deposits,omitempty" ssz-max:"134217728"`
|
||||
PendingPartialWithdrawals []*PendingPartialWithdrawal `protobuf:"bytes,12008,rep,name=pending_partial_withdrawals,json=pendingPartialWithdrawals,proto3" json:"pending_partial_withdrawals,omitempty" ssz-max:"134217728"`
|
||||
@@ -2113,18 +2114,18 @@ func (x *BeaconStateElectra) GetDepositReceiptsStartIndex() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BeaconStateElectra) GetDepositBalanceToConsume() uint64 {
|
||||
func (x *BeaconStateElectra) GetDepositBalanceToConsume() github_com_prysmaticlabs_prysm_v5_math.Gwei {
|
||||
if x != nil {
|
||||
return x.DepositBalanceToConsume
|
||||
}
|
||||
return 0
|
||||
return github_com_prysmaticlabs_prysm_v5_math.Gwei(0)
|
||||
}
|
||||
|
||||
func (x *BeaconStateElectra) GetExitBalanceToConsume() uint64 {
|
||||
func (x *BeaconStateElectra) GetExitBalanceToConsume() github_com_prysmaticlabs_prysm_v5_math.Gwei {
|
||||
if x != nil {
|
||||
return x.ExitBalanceToConsume
|
||||
}
|
||||
return 0
|
||||
return github_com_prysmaticlabs_prysm_v5_math.Gwei(0)
|
||||
}
|
||||
|
||||
func (x *BeaconStateElectra) GetEarliestExitEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch {
|
||||
@@ -2134,11 +2135,11 @@ func (x *BeaconStateElectra) GetEarliestExitEpoch() github_com_prysmaticlabs_pry
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0)
|
||||
}
|
||||
|
||||
func (x *BeaconStateElectra) GetConsolidationBalanceToConsume() uint64 {
|
||||
func (x *BeaconStateElectra) GetConsolidationBalanceToConsume() github_com_prysmaticlabs_prysm_v5_math.Gwei {
|
||||
if x != nil {
|
||||
return x.ConsolidationBalanceToConsume
|
||||
}
|
||||
return 0
|
||||
return github_com_prysmaticlabs_prysm_v5_math.Gwei(0)
|
||||
}
|
||||
|
||||
func (x *BeaconStateElectra) GetEarliestConsolidationEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch {
|
||||
@@ -3010,7 +3011,7 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_rawDesc = []byte{
|
||||
0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72,
|
||||
0x79, 0x42, 0x0c, 0x92, 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52,
|
||||
0x13, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61,
|
||||
0x72, 0x69, 0x65, 0x73, 0x22, 0xfa, 0x17, 0x0a, 0x12, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53,
|
||||
0x72, 0x69, 0x65, 0x73, 0x22, 0x8d, 0x19, 0x0a, 0x12, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53,
|
||||
0x74, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x67,
|
||||
0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0xe9, 0x07, 0x20, 0x01,
|
||||
0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12,
|
||||
@@ -3151,85 +3152,94 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_rawDesc = []byte{
|
||||
0x69, 0x70, 0x74, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x18, 0xe1, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
|
||||
0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x12, 0x3c, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x62, 0x61,
|
||||
0x65, 0x78, 0x12, 0x6d, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x62, 0x61,
|
||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65,
|
||||
0x18, 0xe2, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
|
||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65,
|
||||
0x12, 0x36, 0x0a, 0x17, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x18, 0xe3, 0x5d, 0x20, 0x01,
|
||||
0x28, 0x04, 0x52, 0x14, 0x65, 0x78, 0x69, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54,
|
||||
0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x77, 0x0a, 0x13, 0x65, 0x61, 0x72, 0x6c,
|
||||
0x69, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18,
|
||||
0xe4, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68,
|
||||
0x18, 0xe2, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x2f, 0x82, 0xb5, 0x18, 0x2b, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69,
|
||||
0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x6d,
|
||||
0x61, 0x74, 0x68, 0x2e, 0x47, 0x77, 0x65, 0x69, 0x52, 0x17, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69,
|
||||
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d,
|
||||
0x65, 0x12, 0x67, 0x0a, 0x17, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x18, 0xe3, 0x5d, 0x20,
|
||||
0x01, 0x28, 0x04, 0x42, 0x2f, 0x82, 0xb5, 0x18, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62,
|
||||
0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e,
|
||||
0x47, 0x77, 0x65, 0x69, 0x52, 0x14, 0x65, 0x78, 0x69, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x77, 0x0a, 0x13, 0x65, 0x61,
|
||||
0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63,
|
||||
0x68, 0x18, 0xe4, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74,
|
||||
0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f,
|
||||
0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68,
|
||||
0x52, 0x11, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x45, 0x78, 0x69, 0x74, 0x45, 0x70,
|
||||
0x6f, 0x63, 0x68, 0x12, 0x79, 0x0a, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x18, 0xe5, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x2f,
|
||||
0x82, 0xb5, 0x18, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70,
|
||||
0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79,
|
||||
0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x47, 0x77, 0x65, 0x69, 0x52,
|
||||
0x1d, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61,
|
||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x89,
|
||||
0x01, 0x0a, 0x1c, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18,
|
||||
0xe6, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63,
|
||||
0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72,
|
||||
0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x11,
|
||||
0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x45, 0x78, 0x69, 0x74, 0x45, 0x70, 0x6f, 0x63,
|
||||
0x68, 0x12, 0x48, 0x0a, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x75, 0x6d, 0x65, 0x18, 0xe5, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1d, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x1c,
|
||||
0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0xe6, 0x5d, 0x20,
|
||||
0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62,
|
||||
0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69,
|
||||
0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x1a, 0x65, 0x61, 0x72,
|
||||
0x6c, 0x69, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x76, 0x0a, 0x18, 0x70, 0x65, 0x6e, 0x64, 0x69,
|
||||
0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73,
|
||||
0x69, 0x74, 0x73, 0x18, 0xe7, 0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68,
|
||||
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
|
||||
0x61, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x0d, 0x92, 0xb5, 0x18, 0x09, 0x31, 0x33,
|
||||
0x34, 0x32, 0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12,
|
||||
0x7f, 0x0a, 0x1b, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69,
|
||||
0x61, 0x6c, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, 0xe8,
|
||||
0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
|
||||
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68,
|
||||
0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x42, 0x0d, 0x92, 0xb5, 0x18, 0x09, 0x31, 0x33, 0x34, 0x32,
|
||||
0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x19, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61,
|
||||
0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73,
|
||||
0x12, 0x6f, 0x0a, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe9, 0x5d, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68,
|
||||
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a,
|
||||
0x92, 0xb5, 0x18, 0x06, 0x32, 0x36, 0x32, 0x31, 0x34, 0x34, 0x52, 0x15, 0x70, 0x65, 0x6e, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x22, 0x8d, 0x01, 0x0a, 0x08, 0x50, 0x6f, 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x25,
|
||||
0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02,
|
||||
0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x31,
|
||||
0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c,
|
||||
0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32,
|
||||
0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74,
|
||||
0x79, 0x22, 0x7f, 0x0a, 0x11, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53,
|
||||
0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x34, 0x0a, 0x12, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
|
||||
0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x10, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x34, 0x0a, 0x12,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x72, 0x6f,
|
||||
0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32,
|
||||
0x52, 0x10, 0x73, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x6f,
|
||||
0x6f, 0x74, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x1a,
|
||||
0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x76, 0x0a, 0x18, 0x70, 0x65,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x64, 0x65,
|
||||
0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0xe7, 0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
|
||||
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61,
|
||||
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x6c,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x0d, 0x92, 0xb5, 0x18,
|
||||
0x09, 0x31, 0x33, 0x34, 0x32, 0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x16, 0x70, 0x65, 0x6e, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69,
|
||||
0x74, 0x73, 0x12, 0x7f, 0x0a, 0x1b, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61,
|
||||
0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c,
|
||||
0x73, 0x18, 0xe8, 0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
|
||||
0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70,
|
||||
0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72,
|
||||
0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68,
|
||||
0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e,
|
||||
0x56, 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57,
|
||||
0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x42, 0x0d, 0x92, 0xb5, 0x18, 0x09, 0x31,
|
||||
0x33, 0x34, 0x32, 0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x19, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77,
|
||||
0x61, 0x6c, 0x73, 0x12, 0x6f, 0x0a, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63,
|
||||
0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe9, 0x5d,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
|
||||
0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x6e,
|
||||
0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x42, 0x0a, 0x92, 0xb5, 0x18, 0x06, 0x32, 0x36, 0x32, 0x31, 0x34, 0x34, 0x52, 0x15, 0x70,
|
||||
0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x08, 0x50, 0x6f, 0x77, 0x42, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a,
|
||||
0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73,
|
||||
0x68, 0x12, 0x31, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x69,
|
||||
0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18,
|
||||
0x02, 0x33, 0x32, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63,
|
||||
0x75, 0x6c, 0x74, 0x79, 0x22, 0x7f, 0x0a, 0x11, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63,
|
||||
0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x34, 0x0a, 0x12, 0x62, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x10, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x74, 0x12,
|
||||
0x34, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
|
||||
0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18,
|
||||
0x02, 0x33, 0x32, 0x52, 0x10, 0x73, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72,
|
||||
0x79, 0x52, 0x6f, 0x6f, 0x74, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
|
||||
0x68, 0x61, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65,
|
||||
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62,
|
||||
0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b,
|
||||
0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45,
|
||||
0x74, 0x68, 0x2e, 0x56, 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70,
|
||||
0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -397,10 +397,10 @@ message BeaconStateElectra {
|
||||
|
||||
// Fields introduced in EIP-7251 fork [12001-13000]
|
||||
uint64 deposit_receipts_start_index = 12001;
|
||||
uint64 deposit_balance_to_consume = 12002;
|
||||
uint64 exit_balance_to_consume = 12003;
|
||||
uint64 deposit_balance_to_consume = 12002 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/math.Gwei"];
|
||||
uint64 exit_balance_to_consume = 12003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/math.Gwei"];
|
||||
uint64 earliest_exit_epoch = 12004 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"];
|
||||
uint64 consolidation_balance_to_consume = 12005;
|
||||
uint64 consolidation_balance_to_consume = 12005 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/math.Gwei"];
|
||||
uint64 earliest_consolidation_epoch = 12006 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"];
|
||||
repeated PendingBalanceDeposit pending_balance_deposits = 12007 [(ethereum.eth.ext.ssz_max) = "pending_balance_deposits_limit"];
|
||||
repeated PendingPartialWithdrawal pending_partial_withdrawals = 12008 [(ethereum.eth.ext.ssz_max) = "pending_partial_withdrawals_limit"];
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: ae92821338b1fc2296cda7b35445bbd7005303c62eab0bcef3ef9c4c7cf0b9ef
|
||||
// Hash: 4e7c07afe12b97ee034415333c33967cab8cf624f3fd43f37562cd6307760ec3
|
||||
package eth
|
||||
|
||||
import (
|
||||
ssz "github.com/prysmaticlabs/fastssz"
|
||||
github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
github_com_prysmaticlabs_prysm_v5_math "github.com/prysmaticlabs/prysm/v5/math"
|
||||
v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
)
|
||||
|
||||
@@ -17646,16 +17647,16 @@ func (b *BeaconStateElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = ssz.MarshalUint64(dst, b.DepositReceiptsStartIndex)
|
||||
|
||||
// Field (29) 'DepositBalanceToConsume'
|
||||
dst = ssz.MarshalUint64(dst, b.DepositBalanceToConsume)
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.DepositBalanceToConsume))
|
||||
|
||||
// Field (30) 'ExitBalanceToConsume'
|
||||
dst = ssz.MarshalUint64(dst, b.ExitBalanceToConsume)
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.ExitBalanceToConsume))
|
||||
|
||||
// Field (31) 'EarliestExitEpoch'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.EarliestExitEpoch))
|
||||
|
||||
// Field (32) 'ConsolidationBalanceToConsume'
|
||||
dst = ssz.MarshalUint64(dst, b.ConsolidationBalanceToConsume)
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.ConsolidationBalanceToConsume))
|
||||
|
||||
// Field (33) 'EarliestConsolidationEpoch'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.EarliestConsolidationEpoch))
|
||||
@@ -17979,16 +17980,16 @@ func (b *BeaconStateElectra) UnmarshalSSZ(buf []byte) error {
|
||||
b.DepositReceiptsStartIndex = ssz.UnmarshallUint64(buf[2736653:2736661])
|
||||
|
||||
// Field (29) 'DepositBalanceToConsume'
|
||||
b.DepositBalanceToConsume = ssz.UnmarshallUint64(buf[2736661:2736669])
|
||||
b.DepositBalanceToConsume = github_com_prysmaticlabs_prysm_v5_math.Gwei(ssz.UnmarshallUint64(buf[2736661:2736669]))
|
||||
|
||||
// Field (30) 'ExitBalanceToConsume'
|
||||
b.ExitBalanceToConsume = ssz.UnmarshallUint64(buf[2736669:2736677])
|
||||
b.ExitBalanceToConsume = github_com_prysmaticlabs_prysm_v5_math.Gwei(ssz.UnmarshallUint64(buf[2736669:2736677]))
|
||||
|
||||
// Field (31) 'EarliestExitEpoch'
|
||||
b.EarliestExitEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736677:2736685]))
|
||||
|
||||
// Field (32) 'ConsolidationBalanceToConsume'
|
||||
b.ConsolidationBalanceToConsume = ssz.UnmarshallUint64(buf[2736685:2736693])
|
||||
b.ConsolidationBalanceToConsume = github_com_prysmaticlabs_prysm_v5_math.Gwei(ssz.UnmarshallUint64(buf[2736685:2736693]))
|
||||
|
||||
// Field (33) 'EarliestConsolidationEpoch'
|
||||
b.EarliestConsolidationEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736693:2736701]))
|
||||
@@ -18567,16 +18568,16 @@ func (b *BeaconStateElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
hh.PutUint64(b.DepositReceiptsStartIndex)
|
||||
|
||||
// Field (29) 'DepositBalanceToConsume'
|
||||
hh.PutUint64(b.DepositBalanceToConsume)
|
||||
hh.PutUint64(uint64(b.DepositBalanceToConsume))
|
||||
|
||||
// Field (30) 'ExitBalanceToConsume'
|
||||
hh.PutUint64(b.ExitBalanceToConsume)
|
||||
hh.PutUint64(uint64(b.ExitBalanceToConsume))
|
||||
|
||||
// Field (31) 'EarliestExitEpoch'
|
||||
hh.PutUint64(uint64(b.EarliestExitEpoch))
|
||||
|
||||
// Field (32) 'ConsolidationBalanceToConsume'
|
||||
hh.PutUint64(b.ConsolidationBalanceToConsume)
|
||||
hh.PutUint64(uint64(b.ConsolidationBalanceToConsume))
|
||||
|
||||
// Field (33) 'EarliestConsolidationEpoch'
|
||||
hh.PutUint64(uint64(b.EarliestConsolidationEpoch))
|
||||
|
||||
@@ -7,8 +7,10 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/ssz_static",
|
||||
visibility = ["//testing/spectest:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/spectest/shared/common/ssz_static:go_default_library",
|
||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package ssz_static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
fssz "github.com/prysmaticlabs/fastssz"
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/ssz_static"
|
||||
)
|
||||
|
||||
@@ -16,26 +19,21 @@ func RunSSZStaticTests(t *testing.T, config string) {
|
||||
}
|
||||
|
||||
func customHtr(t *testing.T, htrs []common.HTR, object interface{}) []common.HTR {
|
||||
// TODO: Replace BeaconStateDeneb with BeaconStateElectra below and uncomment the code
|
||||
//_, ok := object.(*ethpb.BeaconStateDeneb)
|
||||
//if !ok {
|
||||
// return htrs
|
||||
//}
|
||||
//
|
||||
//htrs = append(htrs, func(s interface{}) ([32]byte, error) {
|
||||
// beaconState, err := state_native.InitializeFromProtoDeneb(s.(*ethpb.BeaconStateDeneb))
|
||||
// require.NoError(t, err)
|
||||
// return beaconState.HashTreeRoot(context.Background())
|
||||
//})
|
||||
_, ok := object.(*ethpb.BeaconStateElectra)
|
||||
if !ok {
|
||||
return htrs
|
||||
}
|
||||
|
||||
htrs = append(htrs, func(s interface{}) ([32]byte, error) {
|
||||
beaconState, err := state_native.InitializeFromProtoElectra(s.(*ethpb.BeaconStateElectra))
|
||||
require.NoError(t, err)
|
||||
return beaconState.HashTreeRoot(context.Background())
|
||||
})
|
||||
return htrs
|
||||
}
|
||||
|
||||
// UnmarshalledSSZ unmarshalls serialized input.
|
||||
func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (interface{}, error) {
|
||||
// TODO: Remove this check once BeaconState custom HTR function is ready
|
||||
if folderName == "BeaconState" {
|
||||
t.Skip("BeaconState is not ready")
|
||||
}
|
||||
var obj interface{}
|
||||
switch folderName {
|
||||
case "ExecutionPayload":
|
||||
|
||||
@@ -16,6 +16,7 @@ go_library(
|
||||
"deneb.go",
|
||||
"deneb_state.go",
|
||||
"deposits.go",
|
||||
"electra.go",
|
||||
"helpers.go",
|
||||
"merge.go",
|
||||
"state.go",
|
||||
|
||||
@@ -1140,6 +1140,19 @@ func HydrateSignedBeaconBlockDeneb(b *ethpb.SignedBeaconBlockDeneb) *ethpb.Signe
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateSignedBeaconBlockElectra hydrates a signed beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateSignedBeaconBlockElectra(b *ethpb.SignedBeaconBlockElectra) *ethpb.SignedBeaconBlockElectra {
|
||||
if b == nil {
|
||||
b = ðpb.SignedBeaconBlockElectra{}
|
||||
}
|
||||
if b.Signature == nil {
|
||||
b.Signature = make([]byte, fieldparams.BLSSignatureLength)
|
||||
}
|
||||
b.Block = HydrateBeaconBlockElectra(b.Block)
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateSignedBeaconBlockContentsDeneb hydrates a signed beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateSignedBeaconBlockContentsDeneb(b *ethpb.SignedBeaconBlockContentsDeneb) *ethpb.SignedBeaconBlockContentsDeneb {
|
||||
@@ -1173,6 +1186,22 @@ func HydrateBeaconBlockDeneb(b *ethpb.BeaconBlockDeneb) *ethpb.BeaconBlockDeneb
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateBeaconBlockElectra hydrates a beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateBeaconBlockElectra(b *ethpb.BeaconBlockElectra) *ethpb.BeaconBlockElectra {
|
||||
if b == nil {
|
||||
b = ðpb.BeaconBlockElectra{}
|
||||
}
|
||||
if b.ParentRoot == nil {
|
||||
b.ParentRoot = make([]byte, fieldparams.RootLength)
|
||||
}
|
||||
if b.StateRoot == nil {
|
||||
b.StateRoot = make([]byte, fieldparams.RootLength)
|
||||
}
|
||||
b.Body = HydrateBeaconBlockBodyElectra(b.Body)
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateV2BeaconBlockDeneb hydrates a v2 beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateV2BeaconBlockDeneb(b *v2.BeaconBlockDeneb) *v2.BeaconBlockDeneb {
|
||||
@@ -1231,6 +1260,50 @@ func HydrateBeaconBlockBodyDeneb(b *ethpb.BeaconBlockBodyDeneb) *ethpb.BeaconBlo
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateBeaconBlockBodyElectra hydrates a beacon block body with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateBeaconBlockBodyElectra(b *ethpb.BeaconBlockBodyElectra) *ethpb.BeaconBlockBodyElectra {
|
||||
if b == nil {
|
||||
b = ðpb.BeaconBlockBodyElectra{}
|
||||
}
|
||||
if b.RandaoReveal == nil {
|
||||
b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength)
|
||||
}
|
||||
if b.Graffiti == nil {
|
||||
b.Graffiti = make([]byte, fieldparams.RootLength)
|
||||
}
|
||||
if b.Eth1Data == nil {
|
||||
b.Eth1Data = ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
}
|
||||
}
|
||||
if b.SyncAggregate == nil {
|
||||
b.SyncAggregate = ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength),
|
||||
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
}
|
||||
}
|
||||
if b.ExecutionPayload == nil {
|
||||
b.ExecutionPayload = &enginev1.ExecutionPayloadElectra{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||
ExtraData: make([]byte, 0),
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
Transactions: make([][]byte, 0),
|
||||
Withdrawals: make([]*enginev1.Withdrawal, 0),
|
||||
DepositReceipts: make([]*enginev1.DepositReceipt, 0),
|
||||
WithdrawalRequests: make([]*enginev1.ExecutionLayerWithdrawalRequest, 0),
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateV2BeaconBlockBodyDeneb hydrates a v2 beacon block body with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateV2BeaconBlockBodyDeneb(b *v2.BeaconBlockBodyDeneb) *v2.BeaconBlockBodyDeneb {
|
||||
@@ -1283,6 +1356,16 @@ func HydrateSignedBlindedBeaconBlockDeneb(b *ethpb.SignedBlindedBeaconBlockDeneb
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateSignedBlindedBeaconBlockElectra hydrates a signed blinded beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateSignedBlindedBeaconBlockElectra(b *ethpb.SignedBlindedBeaconBlockElectra) *ethpb.SignedBlindedBeaconBlockElectra {
|
||||
if b.Signature == nil {
|
||||
b.Signature = make([]byte, fieldparams.BLSSignatureLength)
|
||||
}
|
||||
b.Message = HydrateBlindedBeaconBlockElectra(b.Message)
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateV2SignedBlindedBeaconBlockDeneb hydrates a signed v2 blinded beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateV2SignedBlindedBeaconBlockDeneb(b *v2.SignedBlindedBeaconBlockDeneb) *v2.SignedBlindedBeaconBlockDeneb {
|
||||
@@ -1309,6 +1392,22 @@ func HydrateBlindedBeaconBlockDeneb(b *ethpb.BlindedBeaconBlockDeneb) *ethpb.Bli
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateBlindedBeaconBlockElectra hydrates a blinded beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateBlindedBeaconBlockElectra(b *ethpb.BlindedBeaconBlockElectra) *ethpb.BlindedBeaconBlockElectra {
|
||||
if b == nil {
|
||||
b = ðpb.BlindedBeaconBlockElectra{}
|
||||
}
|
||||
if b.ParentRoot == nil {
|
||||
b.ParentRoot = make([]byte, fieldparams.RootLength)
|
||||
}
|
||||
if b.StateRoot == nil {
|
||||
b.StateRoot = make([]byte, fieldparams.RootLength)
|
||||
}
|
||||
b.Body = HydrateBlindedBeaconBlockBodyElectra(b.Body)
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateV2BlindedBeaconBlockDeneb hydrates a v2 blinded beacon block with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateV2BlindedBeaconBlockDeneb(b *v2.BlindedBeaconBlockDeneb) *v2.BlindedBeaconBlockDeneb {
|
||||
@@ -1367,6 +1466,50 @@ func HydrateBlindedBeaconBlockBodyDeneb(b *ethpb.BlindedBeaconBlockBodyDeneb) *e
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateBlindedBeaconBlockBodyElectra hydrates a blinded beacon block body with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateBlindedBeaconBlockBodyElectra(b *ethpb.BlindedBeaconBlockBodyElectra) *ethpb.BlindedBeaconBlockBodyElectra {
|
||||
if b == nil {
|
||||
b = ðpb.BlindedBeaconBlockBodyElectra{}
|
||||
}
|
||||
if b.RandaoReveal == nil {
|
||||
b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength)
|
||||
}
|
||||
if b.Graffiti == nil {
|
||||
b.Graffiti = make([]byte, 32)
|
||||
}
|
||||
if b.Eth1Data == nil {
|
||||
b.Eth1Data = ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, 32),
|
||||
}
|
||||
}
|
||||
if b.SyncAggregate == nil {
|
||||
b.SyncAggregate = ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength),
|
||||
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
}
|
||||
}
|
||||
if b.ExecutionPayloadHeader == nil {
|
||||
b.ExecutionPayloadHeader = &enginev1.ExecutionPayloadHeaderElectra{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
ExtraData: make([]byte, 0),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
TransactionsRoot: make([]byte, fieldparams.RootLength),
|
||||
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
|
||||
WithdrawalRequestsRoot: make([]byte, fieldparams.RootLength),
|
||||
DepositReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// HydrateV2BlindedBeaconBlockBodyDeneb hydrates a blinded v2 beacon block body with correct field length sizes
|
||||
// to comply with fssz marshalling and unmarshalling rules.
|
||||
func HydrateV2BlindedBeaconBlockBodyDeneb(b *v2.BlindedBeaconBlockBodyDeneb) *v2.BlindedBeaconBlockBodyDeneb {
|
||||
|
||||
@@ -2,7 +2,6 @@ package util
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
@@ -187,19 +186,3 @@ func ExtendBlocksPlusBlobs(t *testing.T, blks []blocks.ROBlock, size int) ([]blo
|
||||
|
||||
return blks, blobs
|
||||
}
|
||||
|
||||
// HackDenebMaxuint is helpful for tests that need to set up cases where the deneb fork has passed.
|
||||
// We have unit tests that assert our config matches the upstream config, where the next fork is always
|
||||
// set to MaxUint64 until the fork epoch is formally set. This creates an issue for tests that want to
|
||||
// work with slots that are defined to be after deneb because converting the max epoch to a slot leads
|
||||
// to multiplication overflow.
|
||||
// Monkey patching tests with this function is the simplest workaround in these cases.
|
||||
func HackDenebMaxuint(t *testing.T) func() {
|
||||
bc := params.MainnetConfig().Copy()
|
||||
bc.DenebForkEpoch = math.MaxUint32
|
||||
undo, err := params.SetActiveWithUndo(bc)
|
||||
require.NoError(t, err)
|
||||
return func() {
|
||||
require.NoError(t, undo())
|
||||
}
|
||||
}
|
||||
|
||||
25
testing/util/electra.go
Normal file
25
testing/util/electra.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
// HackElectraMaxuint is helpful for tests that need to set up cases where the electra fork has passed.
|
||||
// We have unit tests that assert our config matches the upstream config, where the next fork is always
|
||||
// set to MaxUint64 until the fork epoch is formally set. This creates an issue for tests that want to
|
||||
// work with slots that are defined to be after electra because converting the max epoch to a slot leads
|
||||
// to multiplication overflow.
|
||||
// Monkey patching tests with this function is the simplest workaround in these cases.
|
||||
func HackElectraMaxuint(t *testing.T) func() {
|
||||
bc := params.MainnetConfig().Copy()
|
||||
bc.ElectraForkEpoch = math.MaxUint32
|
||||
undo, err := params.SetActiveWithUndo(bc)
|
||||
require.NoError(t, err)
|
||||
return func() {
|
||||
require.NoError(t, undo())
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,10 @@ func NewBeaconBlockDeneb() *ethpb.SignedBeaconBlockDeneb {
|
||||
return HydrateSignedBeaconBlockDeneb(ðpb.SignedBeaconBlockDeneb{})
|
||||
}
|
||||
|
||||
func NewBeaconBlockElectra() *ethpb.SignedBeaconBlockElectra {
|
||||
return HydrateSignedBeaconBlockElectra(ðpb.SignedBeaconBlockElectra{})
|
||||
}
|
||||
|
||||
// NewBeaconBlockContentsDeneb creates a beacon block with minimum marshalable fields.
|
||||
func NewBeaconBlockContentsDeneb() *ethpb.SignedBeaconBlockContentsDeneb {
|
||||
return HydrateSignedBeaconBlockContentsDeneb(ðpb.SignedBeaconBlockContentsDeneb{})
|
||||
@@ -45,6 +49,11 @@ func NewBlindedBeaconBlockDeneb() *ethpb.SignedBlindedBeaconBlockDeneb {
|
||||
return HydrateSignedBlindedBeaconBlockDeneb(ðpb.SignedBlindedBeaconBlockDeneb{})
|
||||
}
|
||||
|
||||
// NewBlindedBeaconBlockElectra creates a blinded beacon block with minimum marshalable fields.
|
||||
func NewBlindedBeaconBlockElectra() *ethpb.SignedBlindedBeaconBlockElectra {
|
||||
return HydrateSignedBlindedBeaconBlockElectra(ðpb.SignedBlindedBeaconBlockElectra{})
|
||||
}
|
||||
|
||||
// NewBlindedBeaconBlockCapellaV2 creates a blinded beacon block with minimum marshalable fields.
|
||||
func NewBlindedBeaconBlockCapellaV2() *v2.SignedBlindedBeaconBlockCapella {
|
||||
return HydrateV2SignedBlindedBeaconBlockCapella(&v2.SignedBlindedBeaconBlockCapella{})
|
||||
|
||||
@@ -386,6 +386,76 @@ func NewBeaconStateDeneb(options ...func(state *ethpb.BeaconStateDeneb) error) (
|
||||
return st.Copy(), nil
|
||||
}
|
||||
|
||||
// NewBeaconStateElectra creates a beacon state with minimum marshalable fields.
|
||||
func NewBeaconStateElectra(options ...func(state *ethpb.BeaconStateElectra) error) (state.BeaconState, error) {
|
||||
pubkeys := make([][]byte, 512)
|
||||
for i := range pubkeys {
|
||||
pubkeys[i] = make([]byte, 48)
|
||||
}
|
||||
|
||||
seed := ðpb.BeaconStateElectra{
|
||||
BlockRoots: filledByteSlice2D(uint64(params.BeaconConfig().SlotsPerHistoricalRoot), 32),
|
||||
StateRoots: filledByteSlice2D(uint64(params.BeaconConfig().SlotsPerHistoricalRoot), 32),
|
||||
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
|
||||
RandaoMixes: filledByteSlice2D(uint64(params.BeaconConfig().EpochsPerHistoricalVector), 32),
|
||||
Validators: make([]*ethpb.Validator, 0),
|
||||
CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, 32),
|
||||
},
|
||||
Fork: ðpb.Fork{
|
||||
PreviousVersion: make([]byte, 4),
|
||||
CurrentVersion: make([]byte, 4),
|
||||
},
|
||||
Eth1DataVotes: make([]*ethpb.Eth1Data, 0),
|
||||
HistoricalRoots: make([][]byte, 0),
|
||||
JustificationBits: bitfield.Bitvector4{0x0},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
|
||||
LatestBlockHeader: HydrateBeaconHeader(ðpb.BeaconBlockHeader{}),
|
||||
PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
|
||||
PreviousEpochParticipation: make([]byte, 0),
|
||||
CurrentEpochParticipation: make([]byte, 0),
|
||||
CurrentSyncCommittee: ðpb.SyncCommittee{
|
||||
Pubkeys: pubkeys,
|
||||
AggregatePubkey: make([]byte, 48),
|
||||
},
|
||||
NextSyncCommittee: ðpb.SyncCommittee{
|
||||
Pubkeys: pubkeys,
|
||||
AggregatePubkey: make([]byte, 48),
|
||||
},
|
||||
LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderElectra{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, 32),
|
||||
ReceiptsRoot: make([]byte, 32),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, 32),
|
||||
ExtraData: make([]byte, 0),
|
||||
BaseFeePerGas: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
TransactionsRoot: make([]byte, 32),
|
||||
WithdrawalsRoot: make([]byte, 32),
|
||||
DepositReceiptsRoot: make([]byte, 32),
|
||||
WithdrawalRequestsRoot: make([]byte, 32),
|
||||
},
|
||||
}
|
||||
|
||||
for _, opt := range options {
|
||||
err := opt(seed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var st, err = state_native.InitializeFromProtoUnsafeElectra(seed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return st.Copy(), nil
|
||||
}
|
||||
|
||||
// SSZ will fill 2D byte slices with their respective values, so we must fill these in too for round
|
||||
// trip testing.
|
||||
func filledByteSlice2D(length, innerLen uint64) [][]byte {
|
||||
|
||||
@@ -59,6 +59,16 @@ func TestNewBeaconStateDeneb(t *testing.T) {
|
||||
assert.DeepEqual(t, st.ToProtoUnsafe(), got)
|
||||
}
|
||||
|
||||
func TestNewBeaconStateElectra(t *testing.T) {
|
||||
st, err := NewBeaconStateElectra()
|
||||
require.NoError(t, err)
|
||||
b, err := st.MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
got := ðpb.BeaconStateElectra{}
|
||||
require.NoError(t, got.UnmarshalSSZ(b))
|
||||
assert.DeepEqual(t, st.ToProtoUnsafe(), got)
|
||||
}
|
||||
|
||||
func TestNewBeaconState_HashTreeRoot(t *testing.T) {
|
||||
st, err := NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
@@ -76,4 +86,12 @@ func TestNewBeaconState_HashTreeRoot(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = st.HashTreeRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
st, err = NewBeaconStateDeneb()
|
||||
require.NoError(t, err)
|
||||
_, err = st.HashTreeRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
st, err = NewBeaconStateElectra()
|
||||
require.NoError(t, err)
|
||||
_, err = st.HashTreeRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user