Skip to content

Commit

Permalink
skip eth1data voting after electra (#14835)
Browse files Browse the repository at this point in the history
* wip skip eth1data voting after electra

* updating technique

* adding fix for electra eth1 voting

* fixing linting on test

* seeing if reversing genesis state fixes problem

* increasing safety of legacy check

* review feedback

* forgot to fix tests

* nishant's feedback

* nishant's feedback

* rename function a little

* Update beacon-chain/core/helpers/legacy.go

Co-authored-by: Jun Song <[email protected]>

* fixing naming

---------

Co-authored-by: Jun Song <[email protected]>
  • Loading branch information
james-prysm and syjn99 authored Jan 31, 2025
1 parent 1069da1 commit d887536
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 113 deletions.
3 changes: 3 additions & 0 deletions beacon-chain/core/helpers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ go_library(
"beacon_committee.go",
"block.go",
"genesis.go",
"legacy.go",
"metrics.go",
"randao.go",
"rewards_penalties.go",
Expand Down Expand Up @@ -52,6 +53,7 @@ go_test(
"attestation_test.go",
"beacon_committee_test.go",
"block_test.go",
"legacy_test.go",
"private_access_fuzz_noop_test.go", # keep
"private_access_test.go",
"randao_test.go",
Expand Down Expand Up @@ -86,5 +88,6 @@ go_test(
"//time:go_default_library",
"//time/slots:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
],
)
20 changes: 20 additions & 0 deletions beacon-chain/core/helpers/legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package helpers

import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
)

// DepositRequestsStarted determines if the deposit requests have started.
func DepositRequestsStarted(beaconState state.BeaconState) bool {
if beaconState.Version() < version.Electra {
return false
}

requestsStartIndex, err := beaconState.DepositRequestsStartIndex()
if err != nil {
return false
}

return beaconState.Eth1DepositIndex() == requestsStartIndex
}
33 changes: 33 additions & 0 deletions beacon-chain/core/helpers/legacy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package helpers_test

import (
"testing"

"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v5/testing/util"
"github.com/stretchr/testify/require"
)

// TestDepositRequestHaveStarted contains several test cases for depositRequestHaveStarted.
func TestDepositRequestHaveStarted(t *testing.T) {
t.Run("Version below Electra returns false", func(t *testing.T) {
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
result := helpers.DepositRequestsStarted(st)
require.False(t, result)
})

t.Run("Version is Electra or higher, no error, but Eth1DepositIndex != requestsStartIndex returns false", func(t *testing.T) {
st, _ := util.DeterministicGenesisStateElectra(t, 1)
require.NoError(t, st.SetEth1DepositIndex(1))
result := helpers.DepositRequestsStarted(st)
require.False(t, result)
})

t.Run("Version is Electra or higher, no error, and Eth1DepositIndex == requestsStartIndex returns true", func(t *testing.T) {
st, _ := util.DeterministicGenesisStateElectra(t, 1)
require.NoError(t, st.SetEth1DepositIndex(33))
require.NoError(t, st.SetDepositRequestsStartIndex(33))
result := helpers.DepositRequestsStarted(st)
require.True(t, result)
})
}
37 changes: 11 additions & 26 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
Expand Down Expand Up @@ -71,6 +72,10 @@ func (vs *Server) packDepositsAndAttestations(
// this eth1data has enough support to be considered for deposits inclusion. If current vote has
// enough support, then use that vote for basis of determining deposits, otherwise use current state
// eth1data.
// In the post-electra phase, this function will usually return an empty list,
// as the legacy deposit process is deprecated. (EIP-6110)
// NOTE: During the transition period, the legacy deposit process
// may still be active and managed. This function handles that scenario.
func (vs *Server) deposits(
ctx context.Context,
beaconState state.BeaconState,
Expand All @@ -87,21 +92,19 @@ func (vs *Server) deposits(
log.Warn("not connected to eth1 node, skip pending deposit insertion")
return []*ethpb.Deposit{}, nil
}

// skip legacy deposits if eth1 deposit index is already at the index of deposit requests start
if helpers.DepositRequestsStarted(beaconState) {
return []*ethpb.Deposit{}, nil
}

// Need to fetch if the deposits up to the state's latest eth1 data matches
// the number of all deposits in this RPC call. If not, then we return nil.
canonicalEth1Data, canonicalEth1DataHeight, err := vs.canonicalEth1Data(ctx, beaconState, currentVote)
if err != nil {
return nil, err
}

// In the post-electra phase, this function will usually return an empty list,
// as the legacy deposit process is deprecated. (EIP-6110)
// NOTE: During the transition period, the legacy deposit process
// may still be active and managed. This function handles that scenario.
if !isLegacyDepositProcessPeriod(beaconState, canonicalEth1Data) {
return []*ethpb.Deposit{}, nil
}

_, genesisEth1Block := vs.Eth1InfoFetcher.GenesisExecutionChainInfo()
if genesisEth1Block.Cmp(canonicalEth1DataHeight) == 0 {
return []*ethpb.Deposit{}, nil
Expand Down Expand Up @@ -285,21 +288,3 @@ func shouldRebuildTrie(totalDepCount, unFinalizedDeps uint64) bool {
unFinalizedCompute := unFinalizedDeps * params.BeaconConfig().DepositContractTreeDepth
return unFinalizedCompute > totalDepCount
}

// isLegacyDepositProcessPeriod determines if the current state should use the legacy deposit process.
func isLegacyDepositProcessPeriod(beaconState state.BeaconState, canonicalEth1Data *ethpb.Eth1Data) bool {
// Before the Electra upgrade, always use the legacy deposit process.
if beaconState.Version() < version.Electra {
return true
}

// Handle the transition period between the legacy and the new deposit process.
requestsStartIndex, err := beaconState.DepositRequestsStartIndex()
if err != nil {
// If we can't get the deposit requests start index,
// we should default to the legacy deposit process.
return true
}
eth1DepositIndexLimit := math.Min(canonicalEth1Data.DepositCount, requestsStartIndex)
return beaconState.Eth1DepositIndex() < eth1DepositIndexLimit
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package validator

import (
"context"
"math"
"math/big"
"testing"

mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache/depositsnapshot"
mockExecution "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/container/trie"
Expand Down Expand Up @@ -214,85 +212,3 @@ func TestProposer_PendingDeposits_Electra(t *testing.T) {
assert.Equal(t, 0, len(deposits), "Received unexpected number of pending deposits")

}

func TestIsLegacyDepositProcessPeriod(t *testing.T) {
tests := []struct {
name string
state state.BeaconState
canonicalEth1Data *ethpb.Eth1Data
want bool
}{
{
name: "pre-electra",
state: func() state.BeaconState {
st, err := state_native.InitializeFromProtoDeneb(&ethpb.BeaconStateDeneb{
Eth1Data: &ethpb.Eth1Data{
BlockHash: []byte("0x0"),
DepositRoot: make([]byte, 32),
DepositCount: 5,
},
Eth1DepositIndex: 1,
})
require.NoError(t, err)
return st
}(),
canonicalEth1Data: &ethpb.Eth1Data{
BlockHash: []byte("0x0"),
DepositRoot: make([]byte, 32),
DepositCount: 5,
},
want: true,
},
{
name: "post-electra, pending deposits from pre-electra",
state: func() state.BeaconState {
st, err := state_native.InitializeFromProtoElectra(&ethpb.BeaconStateElectra{
Eth1Data: &ethpb.Eth1Data{
BlockHash: []byte("0x0"),
DepositRoot: make([]byte, 32),
DepositCount: 5,
},
DepositRequestsStartIndex: math.MaxUint64,
Eth1DepositIndex: 1,
})
require.NoError(t, err)
return st
}(),
canonicalEth1Data: &ethpb.Eth1Data{
BlockHash: []byte("0x0"),
DepositRoot: make([]byte, 32),
DepositCount: 5,
},
want: true,
},
{
name: "post-electra, no pending deposits from pre-alpaca",
state: func() state.BeaconState {
st, err := state_native.InitializeFromProtoElectra(&ethpb.BeaconStateElectra{
Eth1Data: &ethpb.Eth1Data{
BlockHash: []byte("0x0"),
DepositRoot: make([]byte, 32),
DepositCount: 5,
},
DepositRequestsStartIndex: 1,
Eth1DepositIndex: 5,
})
require.NoError(t, err)
return st
}(),
canonicalEth1Data: &ethpb.Eth1Data{
BlockHash: []byte("0x0"),
DepositRoot: make([]byte, 32),
DepositCount: 5,
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := isLegacyDepositProcessPeriod(tt.state, tt.canonicalEth1Data); got != tt.want {
t.Errorf("isLegacyDepositProcessPeriod() = %v, want %v", got, tt.want)
}
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/pkg/errors"
fastssz "github.com/prysmaticlabs/fastssz"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/features"
"github.com/prysmaticlabs/prysm/v5/config/params"
Expand All @@ -30,10 +31,17 @@ import (
// - Otherwise:
// - Determine the vote with the highest count. Prefer the vote with the highest eth1 block height in the event of a tie.
// - This vote's block is the eth1 block to use for the block proposal.
//
// After Electra and eth1 deposit transition period voting will no longer be needed
func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.BeaconState) (*ethpb.Eth1Data, error) {
ctx, cancel := context.WithTimeout(ctx, eth1dataTimeout)
defer cancel()

// post eth1 deposits, the Eth 1 data will then be frozen
if helpers.DepositRequestsStarted(beaconState) {
return beaconState.Eth1Data(), nil
}

slot := beaconState.Slot()
votingPeriodStartTime := vs.slotStartTime(slot)

Expand Down
35 changes: 35 additions & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2698,6 +2698,41 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
expectedHash := []byte("eth1data")
assert.DeepEqual(t, expectedHash, hash)
})

t.Run("post electra the head eth1data should be returned", func(t *testing.T) {
p := mockExecution.New().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(100, latestValidTime, []byte("latest"))
p.Eth1Data = &ethpb.Eth1Data{
BlockHash: []byte("eth1data"),
}

depositCache, err := depositsnapshot.New()
require.NoError(t, err)

beaconState, err := state_native.InitializeFromProtoElectra(&ethpb.BeaconStateElectra{
Slot: slot,
Eth1Data: &ethpb.Eth1Data{BlockHash: []byte("legacy"), DepositCount: 1},
})
require.NoError(t, err)

ps := &Server{
ChainStartFetcher: p,
Eth1InfoFetcher: p,
Eth1BlockFetcher: p,
BlockFetcher: p,
DepositFetcher: depositCache,
}

ctx := context.Background()
majorityVoteEth1Data, err := ps.eth1DataMajorityVote(ctx, beaconState)
require.NoError(t, err)

hash := majorityVoteEth1Data.BlockHash

expectedHash := []byte("legacy")
assert.DeepEqual(t, expectedHash, hash)
})
}

func TestProposer_FilterAttestation(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions changelog/james-prysm_electra-eth1voting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Added

- check to stop eth1 voting after electra and eth1 deposits stop
6 changes: 3 additions & 3 deletions testing/util/electra_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ func genesisBeaconStateElectra(ctx context.Context, deposits []*ethpb.Deposit, g
return buildGenesisBeaconStateElectra(genesisTime, st, st.Eth1Data())
}

// emptyGenesisStateDeneb returns an empty genesis state in Electra format.
// emptyGenesisStateElectra returns an empty genesis state in Electra format.
func emptyGenesisStateElectra() (state.BeaconState, error) {
st := &ethpb.BeaconStateElectra{
// Misc fields.
Slot: 0,
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().BellatrixForkVersion,
CurrentVersion: params.BeaconConfig().DenebForkVersion,
PreviousVersion: params.BeaconConfig().DenebForkVersion,
CurrentVersion: params.BeaconConfig().ElectraForkVersion,
Epoch: 0,
},
// Validator registry fields.
Expand Down

0 comments on commit d887536

Please sign in to comment.