Skip to content

Commit

Permalink
start taking apart GetPayloadBodiesByHash tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kasey committed May 15, 2024
1 parent 82fb791 commit 63fef7b
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 129 deletions.
101 changes: 0 additions & 101 deletions beacon-chain/execution/engine_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,15 +552,6 @@ func (s *Service) GetPayloadBodiesByRange(ctx context.Context, start, count uint
return result, handleRPCError(err)
}

func emptyBody() *pb.ExecutionPayloadBodyV1Or2 {
return &pb.ExecutionPayloadBodyV1Or2{
Transactions: make([]hexutil.Bytes, 0),
Withdrawals: make([]*pb.Withdrawal, 0),
WithdrawalRequests: make([]pb.WithdrawalRequestV1, 0),
DepositRequests: make([]pb.DepositRequestV1, 0),
}
}

// ReconstructFullBlock takes in a blinded beacon block and reconstructs
// a beacon block with a full execution payload via the engine API.
func (s *Service) ReconstructFullBlock(
Expand All @@ -582,98 +573,6 @@ func (s *Service) ReconstructFullBellatrixBlockBatch(
ctx context.Context, blindedBlocks []interfaces.ReadOnlySignedBeaconBlock,
) ([]interfaces.SignedBeaconBlock, error) {
return reconstructBlindedBlockBatch(ctx, s.rpcClient, blindedBlocks)
/*
if len(blindedBlocks) == 0 {
return []interfaces.SignedBeaconBlock{}, nil
}
var executionHashes []common.Hash
var validExecPayloads []int
var zeroExecPayloads []int
for i, b := range blindedBlocks {
if err := blocks.BeaconBlockIsNil(b); err != nil {
return nil, errors.Wrap(err, "cannot reconstruct bellatrix block from nil data")
}
if !b.Block().IsBlinded() {
return nil, errors.New("can only reconstruct block from blinded block format")
}
header, err := b.Block().Body().Execution()
if err != nil {
return nil, err
}
if header.IsNil() {
return nil, errors.New("execution payload header in blinded block was nil")
}
// Determine if the block is pre-merge or post-merge. Depending on the result,
// we will ask the execution engine for the full payload.
if bytes.Equal(header.BlockHash(), params.BeaconConfig().ZeroHash[:]) {
zeroExecPayloads = append(zeroExecPayloads, i)
} else {
executionBlockHash := common.BytesToHash(header.BlockHash())
validExecPayloads = append(validExecPayloads, i)
executionHashes = append(executionHashes, executionBlockHash)
}
}
fullBlocks, err := s.retrievePayloadsFromExecutionHashes(ctx, executionHashes, validExecPayloads, blindedBlocks)
if err != nil {
return nil, err
}
// For blocks that are pre-merge we simply reconstruct them via an empty
// execution payload.
for _, realIdx := range zeroExecPayloads {
bblock := blindedBlocks[realIdx]
payload, err := buildEmptyExecutionPayload(bblock.Version())
if err != nil {
return nil, err
}
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlocks[realIdx], payload)
if err != nil {
return nil, err
}
fullBlocks[realIdx] = fullBlock
}
reconstructedExecutionPayloadCount.Add(float64(len(blindedBlocks)))
return fullBlocks, nil
*/
}

// This method assumes that the provided execution hashes are all valid and part of the
// canonical chain.
func (s *Service) retrievePayloadsFromExecutionHashes(
ctx context.Context,
executionHashes []common.Hash,
validExecPayloads []int,
blindedBlocks []interfaces.ReadOnlySignedBeaconBlock) ([]interfaces.SignedBeaconBlock, error) {

payloadBodies, err := s.GetPayloadBodiesByHash(ctx, executionHashes)
if err != nil {
return nil, fmt.Errorf("could not fetch payload bodies by hash %#x: %v", executionHashes, err)
}
if len(payloadBodies) != len(executionHashes) {
return nil, errors.Wrapf(errInvalidPayloadBodyResponse, "invalid number of payload bodies returned, want=%d, got=%d", len(executionHashes), len(payloadBodies))
}

fullBlocks := make([]interfaces.SignedBeaconBlock, len(blindedBlocks))
// For each valid payload, we reconstruct the full block from it with the
// blinded block.
for sliceIdx, realIdx := range validExecPayloads {
var payload interfaces.ExecutionData
bblock := blindedBlocks[realIdx]
b := payloadBodies[sliceIdx]
header, err := bblock.Block().Body().Execution()
if err != nil {
return nil, err
}
payload, err = fullPayloadFromPayloadBody(header, b, bblock.Version())
if err != nil {
return nil, err
}
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(bblock, payload.Proto())
if err != nil {
return nil, err
}
fullBlocks[realIdx] = fullBlock
}
return fullBlocks, nil
}

func fullPayloadFromPayloadBody(
Expand Down
37 changes: 10 additions & 27 deletions beacon-chain/execution/engine_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util"
"github.com/prysmaticlabs/prysm/v5/time/slots"
logTest "github.com/sirupsen/logrus/hooks/test"
)

Expand Down Expand Up @@ -2077,36 +2078,21 @@ func newPayloadV4Setup(t *testing.T, status *pb.PayloadStatus, payload *pb.Execu
func TestCapella_PayloadBodiesByHash(t *testing.T) {
t.Run("empty response works", func(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
executionPayloadBodies := make([]*pb.ExecutionPayloadBodyV1Or2, 0)
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": executionPayloadBodies,
}
err := json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
t.Fatal("http request should not be made")
}))
ctx := context.Background()

rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)

service := &Service{}
service.rpcClient = rpcClient

results, err := service.GetPayloadBodiesByHash(ctx, []common.Hash{})
results, err := reconstructBlindedBlockBatch(ctx, rpcClient, []interfaces.ReadOnlySignedBeaconBlock{})
require.NoError(t, err)
require.Equal(t, 0, len(results))

for _, item := range results {
require.NotNil(t, item)
}
})
t.Run("single element response null works", func(t *testing.T) {
slot, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
require.NoError(t, err)
blk, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 0)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
Expand All @@ -2128,15 +2114,12 @@ func TestCapella_PayloadBodiesByHash(t *testing.T) {
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)

blinded, err := blk.ToBlinded()
require.NoError(t, err)
service := &Service{}
service.rpcClient = rpcClient

bRoot := [32]byte{}
copy(bRoot[:], "hash")
results, err := service.GetPayloadBodiesByHash(ctx, []common.Hash{bRoot})
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.IsNil(t, results[0])
_, err = service.ReconstructFullBlock(ctx, blinded)
require.ErrorIs(t, err, errNilPayloadBody)
})
t.Run("empty, null, full works", func(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down
4 changes: 3 additions & 1 deletion beacon-chain/execution/payload_body.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"google.golang.org/protobuf/proto"
)

var errNilPayloadBody = errors.New("nil payload body for block")

type blockWithHeader struct {
block interfaces.ReadOnlySignedBeaconBlock
header interfaces.ExecutionData
Expand Down Expand Up @@ -137,7 +139,7 @@ func (r *blindedBlockReconstructor) unblinded() ([]interfaces.SignedBeaconBlock,
} else {
body, ok := r.bodies[bodyKey]
if !ok {
return nil, errors.Errorf("missing payload body for block hash %#x", bodyKey)
return nil, errors.Wrapf(errNilPayloadBody, "hash %#x", bodyKey)
}
ed, err := fullPayloadFromPayloadBody(header, body, blk.Version())
if err != nil {
Expand Down

0 comments on commit 63fef7b

Please sign in to comment.