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 Aug 23, 2024
1 parent 5ba33f7 commit 1da49d3
Show file tree
Hide file tree
Showing 8 changed files with 1,641 additions and 1,304 deletions.
2 changes: 2 additions & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ go_library(
"proposer_capella.go",
"proposer_deneb.go",
"proposer_deposits.go",
"proposer_epbs.go",
"proposer_empty_block.go",
"proposer_eth1data.go",
"proposer_execution_payload.go",
Expand Down Expand Up @@ -201,6 +202,7 @@ go_test(
"proposer_slashings_test.go",
"proposer_sync_aggregate_test.go",
"proposer_test.go",
"proposer_epbs_test.go",
"server_mainnet_test.go",
"server_test.go",
"status_mainnet_test.go",
Expand Down
61 changes: 61 additions & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer_epbs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package validator

import (
"context"

"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
ethpb "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"
)

// GetLocalHeader returns the local header for a given slot and proposer index.
func (vs *Server) GetLocalHeader(ctx context.Context, req *ethpb.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
}
99 changes: 99 additions & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer_epbs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package validator

import (
"context"
"testing"

chainMock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
powtesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing"
doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree"
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"
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"
)

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[:])
})
}
Loading

0 comments on commit 1da49d3

Please sign in to comment.