Skip to content

Commit

Permalink
Prysm rpc: Get local header
Browse files Browse the repository at this point in the history
  • Loading branch information
terencechain committed Sep 28, 2024
1 parent c4550d7 commit 00b32da
Show file tree
Hide file tree
Showing 10 changed files with 1,628 additions and 1,317 deletions.
1 change: 1 addition & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ go_library(
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_x_sync//errgroup:go_default_library",
"@io_opencensus_go//trace:go_default_library",
],
)

Expand Down
52 changes: 52 additions & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer_epbs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epbs"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/time/slots"
"go.opencensus.io/trace"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
Expand Down Expand Up @@ -84,3 +89,50 @@ func (vs *Server) computePostPayloadStateRoot(ctx context.Context, envelope inte
log.WithField("beaconStateRoot", fmt.Sprintf("%#x", root)).Debugf("Computed state root at execution stage")
return root[:], nil
}

// GetLocalHeader returns the local header for a given slot and proposer index.
func (vs *Server) GetLocalHeader(ctx context.Context, req *eth.HeaderRequest) (*enginev1.ExecutionPayloadHeaderEPBS, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.GetLocalHeader")
defer span.End()

if vs.SyncChecker.Syncing() {
return nil, status.Error(codes.FailedPrecondition, "Syncing to latest head, not ready to respond")
}

if err := vs.optimisticStatus(ctx); err != nil {
return nil, status.Errorf(codes.FailedPrecondition, "Validator is not ready to propose: %v", err)
}

slot := req.Slot
epoch := slots.ToEpoch(slot)
if params.BeaconConfig().EPBSForkEpoch > epoch {
return nil, status.Errorf(codes.FailedPrecondition, "EPBS fork has not occurred yet")
}

st, parentRoot, err := vs.getParentState(ctx, slot)
if err != nil {
return nil, err
}

proposerIndex := req.ProposerIndex
localPayload, err := vs.getLocalPayloadFromEngine(ctx, st, parentRoot, slot, proposerIndex)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get local payload: %v", err)
}

kzgRoot, err := ssz.KzgCommitmentsRoot(localPayload.BlobsBundle.KzgCommitments)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get kzg commitments root: %v", err)
}

return &enginev1.ExecutionPayloadHeaderEPBS{
ParentBlockHash: localPayload.ExecutionData.ParentHash(),
ParentBlockRoot: parentRoot[:],
BlockHash: localPayload.ExecutionData.BlockHash(),
GasLimit: localPayload.ExecutionData.GasLimit(),
BuilderIndex: proposerIndex,
Slot: slot,
Value: 0,
BlobKzgCommitmentsRoot: kzgRoot[:],
}, nil
}
89 changes: 89 additions & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer_epbs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,23 @@ import (
"testing"

"github.com/pkg/errors"
chainMock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing"
mockChain "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
dbutil "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing"
mockExecution "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing"
powtesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing"
doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree"
p2ptest "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen"
mockSync "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/initial-sync/testing"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util"
)
Expand Down Expand Up @@ -107,3 +115,84 @@ func TestProposer_ComputePostPayloadStateRoot(t *testing.T) {
require.NoError(t, err)
require.DeepEqual(t, expectedStateRoot[:], stateRoot)
}

func TestServer_GetLocalHeader(t *testing.T) {
t.Run("Node is syncing", func(t *testing.T) {
vs := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: true},
}
_, err := vs.GetLocalHeader(context.Background(), &eth.HeaderRequest{
Slot: 0,
ProposerIndex: 0,
})
require.ErrorContains(t, "Syncing to latest head, not ready to respond", err)
})
t.Run("ePBS fork has not occurred", func(t *testing.T) {
vs := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: &chainMock.ChainService{},
}
_, err := vs.GetLocalHeader(context.Background(), &eth.HeaderRequest{
Slot: 0,
ProposerIndex: 0,
})
require.ErrorContains(t, "EPBS fork has not occurred yet", err)
})
t.Run("Happy case", func(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.EPBSForkEpoch = 1
params.OverrideBeaconConfig(cfg)

st, _ := util.DeterministicGenesisStateEpbs(t, 1)
fc := doublylinkedtree.New()
chainService := &chainMock.ChainService{
ForkChoiceStore: fc,
State: st,
}
payloadIdCache := cache.NewPayloadIDCache()
payloadId := primitives.PayloadID{1}
payloadIdCache.Set(params.BeaconConfig().SlotsPerEpoch, [32]byte{}, payloadId)

payload := &v1.ExecutionPayloadElectra{
ParentHash: []byte{1},
BlockHash: []byte{2},
GasLimit: 1000000,
}
executionData, err := blocks.NewWrappedExecutionData(payload)
require.NoError(t, err)
kzgs := [][]byte{make([]byte, 48), make([]byte, 48), make([]byte, 48)}
vs := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: chainService,
ForkchoiceFetcher: chainService,
HeadFetcher: chainService,
TrackedValidatorsCache: cache.NewTrackedValidatorsCache(),
PayloadIDCache: payloadIdCache,
ExecutionEngineCaller: &powtesting.EngineClient{
GetPayloadResponse: &blocks.GetPayloadResponse{
ExecutionData: executionData,
BlobsBundle: &v1.BlobsBundle{
KzgCommitments: kzgs,
}},
},
}
validatorIndex := primitives.ValidatorIndex(1)
vs.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: validatorIndex})
slot := primitives.Slot(params.BeaconConfig().EPBSForkEpoch) * params.BeaconConfig().SlotsPerEpoch
h, err := vs.GetLocalHeader(context.Background(), &eth.HeaderRequest{
Slot: slot,
ProposerIndex: validatorIndex,
})
require.NoError(t, err)
require.DeepEqual(t, h.ParentBlockHash, payload.ParentHash)
require.DeepEqual(t, h.BlockHash, payload.BlockHash)
require.Equal(t, h.GasLimit, payload.GasLimit)
require.Equal(t, h.BuilderIndex, validatorIndex)
require.Equal(t, h.Slot, slot)
require.Equal(t, h.Value, uint64(0))
kzgRoot, err := ssz.KzgCommitmentsRoot(kzgs)
require.NoError(t, err)
require.DeepEqual(t, h.BlobKzgCommitmentsRoot, kzgRoot[:])
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func (vs *Server) getLocalPayloadFromEngine(
}
var attr payloadattribute.Attributer
switch st.Version() {
case version.Deneb, version.Electra:
case version.Deneb, version.Electra, version.EPBS:
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit 00b32da

Please sign in to comment.