Skip to content

Commit

Permalink
Add ePBS to state (#13926)
Browse files Browse the repository at this point in the history
  • Loading branch information
potuz authored and terencechain committed Jul 20, 2024
1 parent 4cac646 commit 58a1b2f
Show file tree
Hide file tree
Showing 25 changed files with 1,073 additions and 95 deletions.
1 change: 1 addition & 0 deletions beacon-chain/state/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go_library(
srcs = [
"error.go",
"interfaces.go",
"interfaces_epbs.go",
"prometheus.go",
],
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/state",
Expand Down
2 changes: 2 additions & 0 deletions beacon-chain/state/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type ReadOnlyBeaconState interface {
ReadOnlySyncCommittee
ReadOnlyDeposits
ReadOnlyConsolidations
ReadOnlyEpbsFields
ToProtoUnsafe() interface{}
ToProto() interface{}
GenesisTime() uint64
Expand Down Expand Up @@ -94,6 +95,7 @@ type WriteOnlyBeaconState interface {
WriteOnlyConsolidations
WriteOnlyWithdrawals
WriteOnlyDeposits
WriteOnlyEpbsFields
SetGenesisTime(val uint64) error
SetGenesisValidatorsRoot(val []byte) error
SetSlot(val primitives.Slot) error
Expand Down
28 changes: 28 additions & 0 deletions beacon-chain/state/interfaces_epbs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package state

import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
)

type ReadOnlyEpbsFields interface {
PreviousInclusionListSlot() primitives.Slot
PreviousInclusionListProposer() primitives.ValidatorIndex
LatestInclusionListSlot() primitives.Slot
LatestInclusionListProposer() primitives.ValidatorIndex
IsParentBlockFull() bool
ExecutionPayloadHeader() *enginev1.ExecutionPayloadHeaderEPBS
LatestBlockHash() []byte
LatestFullSlot() primitives.Slot
LastWithdrawalsRoot() []byte
}

type WriteOnlyEpbsFields interface {
SetExecutionPayloadHeader(val *enginev1.ExecutionPayloadHeaderEPBS)
UpdatePreviousInclusionListData()
SetLatestInclusionListSlot(val primitives.Slot)
SetLatestInclusionListProposer(val primitives.ValidatorIndex)
SetLatestBlockHash(val []byte)
SetLatestFullSlot(val primitives.Slot)
SetLastWithdrawalsRoot(val []byte)
}
7 changes: 7 additions & 0 deletions beacon-chain/state/state-native/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ go_library(
"getters_checkpoint.go",
"getters_consolidation.go",
"getters_deposit_requests.go",
"getters_epbs.go",
"getters_eth1.go",
"getters_exit.go",
"getters_misc.go",
"getters_participation.go",
"getters_payload_header.go",
"getters_payload_header_epbs.go",
"getters_randao.go",
"getters_state.go",
"getters_sync_committee.go",
Expand All @@ -34,6 +36,7 @@ go_library(
"setters_churn.go",
"setters_consolidation.go",
"setters_deposit_requests.go",
"setters_epbs.go",
"setters_eth1.go",
"setters_misc.go",
"setters_participation.go",
Expand All @@ -46,6 +49,7 @@ go_library(
"spec_parameters.go",
"ssz.go",
"state_trie.go",
"state_trie_epbs.go",
"types.go",
"validator_index_cache.go",
],
Expand Down Expand Up @@ -98,6 +102,7 @@ go_test(
"getters_deposit_requests_test.go",
"getters_exit_test.go",
"getters_participation_test.go",
"getters_setters_epbs_test.go",
"getters_test.go",
"getters_validator_test.go",
"getters_withdrawal_test.go",
Expand All @@ -119,6 +124,7 @@ go_test(
"setters_withdrawal_test.go",
"state_fuzz_test.go",
"state_test.go",
"state_trie_epbs_test.go",
"state_trie_test.go",
"types_test.go",
"validator_index_cache_test.go",
Expand Down Expand Up @@ -152,6 +158,7 @@ go_test(
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"//testing/util/random: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",
Expand Down
9 changes: 9 additions & 0 deletions beacon-chain/state/state-native/beacon_state_mainnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ type BeaconState struct {
latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex primitives.ValidatorIndex
// ePBS fields
previousInclusionListProposer primitives.ValidatorIndex
previousInclusionListSlot primitives.Slot
latestInclusionListProposer primitives.ValidatorIndex
latestInclusionListSlot primitives.Slot
latestBlockHash [32]byte
latestFullSlot primitives.Slot
executionPayloadHeader *enginev1.ExecutionPayloadHeaderEPBS
lastWithdrawalsRoot [32]byte

// Electra fields
depositRequestsStartIndex uint64
Expand Down
9 changes: 9 additions & 0 deletions beacon-chain/state/state-native/beacon_state_minimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ type BeaconState struct {
latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex primitives.ValidatorIndex
// ePBS fields
previousInclusionListProposer primitives.ValidatorIndex
previousInclusionListSlot primitives.Slot
latestInclusionListProposer primitives.ValidatorIndex
latestInclusionListSlot primitives.Slot
latestBlockHash [32]byte
latestFullSlot primitives.Slot
executionPayloadHeader *enginev1.ExecutionPayloadHeaderEPBS
lastWithdrawalsRoot [32]byte

// Electra fields
depositRequestsStartIndex uint64
Expand Down
83 changes: 83 additions & 0 deletions beacon-chain/state/state-native/getters_epbs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package state_native

import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
)

// ExecutionPayloadHeader retrieves a copy of the execution payload header.
// It returns an error if the operation is not supported for the beacon state's version.
func (b *BeaconState) ExecutionPayloadHeader() *enginev1.ExecutionPayloadHeaderEPBS {
b.lock.RLock()
defer b.lock.RUnlock()

return b.executionPayloadHeaderVal()
}

// IsParentBlockFull checks if the last committed payload header was fulfilled.
// Returns true if both the beacon block and payload were present.
// Call this function on a beacon state before processing the execution payload header.
func (b *BeaconState) IsParentBlockFull() bool {
b.lock.RLock()
defer b.lock.RUnlock()

headerBlockHash := bytesutil.ToBytes32(b.executionPayloadHeader.BlockHash)
return headerBlockHash == b.latestBlockHash
}

// LatestInclusionListProposer returns the proposer index from the latest inclusion list.
func (b *BeaconState) LatestInclusionListProposer() primitives.ValidatorIndex {
b.lock.RLock()
defer b.lock.RUnlock()

return b.latestInclusionListProposer
}

// LatestInclusionListSlot returns the slot from the latest inclusion list.
func (b *BeaconState) LatestInclusionListSlot() primitives.Slot {
b.lock.RLock()
defer b.lock.RUnlock()

return b.latestInclusionListSlot
}

// PreviousInclusionListProposer returns the proposer index from the previous inclusion list.
func (b *BeaconState) PreviousInclusionListProposer() primitives.ValidatorIndex {
b.lock.RLock()
defer b.lock.RUnlock()

return b.previousInclusionListProposer
}

// PreviousInclusionListSlot returns the slot from the previous inclusion list.
func (b *BeaconState) PreviousInclusionListSlot() primitives.Slot {
b.lock.RLock()
defer b.lock.RUnlock()

return b.previousInclusionListSlot
}

// LatestBlockHash returns the latest block hash.
func (b *BeaconState) LatestBlockHash() []byte {
b.lock.RLock()
defer b.lock.RUnlock()

return b.latestBlockHash[:]
}

// LatestFullSlot returns the slot of the latest full block.
func (b *BeaconState) LatestFullSlot() primitives.Slot {
b.lock.RLock()
defer b.lock.RUnlock()

return b.latestFullSlot
}

// LastWithdrawalsRoot returns the latest withdrawal root.
func (b *BeaconState) LastWithdrawalsRoot() []byte {
b.lock.RLock()
defer b.lock.RUnlock()

return b.lastWithdrawalsRoot[:]
}
10 changes: 10 additions & 0 deletions beacon-chain/state/state-native/getters_payload_header_epbs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package state_native

import (
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
)

func (b *BeaconState) executionPayloadHeaderVal() *enginev1.ExecutionPayloadHeaderEPBS {
return eth.CopyExecutionPayloadHeaderEPBS(b.executionPayloadHeader)
}
104 changes: 104 additions & 0 deletions beacon-chain/state/state-native/getters_setters_epbs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package state_native

import (
"crypto/rand"
"testing"

"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util/random"
)

func Test_LatestExecutionPayloadHeader(t *testing.T) {
s := &BeaconState{version: version.EPBS}
_, err := s.LatestExecutionPayloadHeader()
require.ErrorContains(t, "unsupported version (epbs) for latest execution payload header", err)
}

func Test_SetLatestExecutionPayloadHeader(t *testing.T) {
s := &BeaconState{version: version.EPBS}
require.ErrorContains(t, "SetLatestExecutionPayloadHeader is not supported for epbs", s.SetLatestExecutionPayloadHeader(nil))
}

func Test_SetExecutionPayloadHeader(t *testing.T) {
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
header := random.ExecutionPayloadHeader(t)
s.SetExecutionPayloadHeader(header)
require.Equal(t, true, s.dirtyFields[types.ExecutionPayloadHeader])

got := s.ExecutionPayloadHeader()
require.DeepEqual(t, got, header)
}

func Test_UpdatePreviousInclusionListData(t *testing.T) {
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
p := s.PreviousInclusionListProposer()
require.Equal(t, primitives.ValidatorIndex(0), p)
ss := s.PreviousInclusionListSlot()
require.Equal(t, primitives.Slot(0), ss)

s.SetLatestInclusionListProposer(1)
s.SetLatestInclusionListSlot(2)
s.UpdatePreviousInclusionListData()
require.Equal(t, true, s.dirtyFields[types.PreviousInclusionListProposer])
require.Equal(t, true, s.dirtyFields[types.PreviousInclusionListSlot])

p = s.PreviousInclusionListProposer()
require.Equal(t, primitives.ValidatorIndex(1), p)
ss = s.PreviousInclusionListSlot()
require.Equal(t, primitives.Slot(2), ss)
}

func Test_SetLatestInclusionListProposer(t *testing.T) {
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
s.SetLatestInclusionListProposer(1)
require.Equal(t, true, s.dirtyFields[types.LatestInclusionListProposer])

got := s.LatestInclusionListProposer()
require.Equal(t, primitives.ValidatorIndex(1), got)
}

func Test_SetLatestInclusionListSlot(t *testing.T) {
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
s.SetLatestInclusionListSlot(2)
require.Equal(t, true, s.dirtyFields[types.LatestInclusionListSlot])

got := s.LatestInclusionListSlot()
require.Equal(t, primitives.Slot(2), got)
}

func Test_SetLatestBlockHash(t *testing.T) {
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
b := make([]byte, fieldparams.RootLength)
_, err := rand.Read(b)
require.NoError(t, err)
s.SetLatestBlockHash(b)
require.Equal(t, true, s.dirtyFields[types.LatestBlockHash])

got := s.LatestBlockHash()
require.DeepEqual(t, got, b)
}

func Test_SetLatestFullSlot(t *testing.T) {
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
s.SetLatestFullSlot(3)
require.Equal(t, true, s.dirtyFields[types.LatestFullSlot])

got := s.LatestFullSlot()
require.Equal(t, primitives.Slot(3), got)
}

func Test_SetLastWithdrawalsRoot(t *testing.T) {
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
b := make([]byte, fieldparams.RootLength)
_, err := rand.Read(b)
require.NoError(t, err)
s.SetLastWithdrawalsRoot(b)
require.Equal(t, true, s.dirtyFields[types.LastWithdrawalsRoot])

got := s.LastWithdrawalsRoot()
require.DeepEqual(t, got, b)
}
Loading

0 comments on commit 58a1b2f

Please sign in to comment.