diff --git a/beacon-chain/execution/engine_client.go b/beacon-chain/execution/engine_client.go index 4cfcce8416ec..438ada79daf2 100644 --- a/beacon-chain/execution/engine_client.go +++ b/beacon-chain/execution/engine_client.go @@ -493,7 +493,12 @@ func (s *Service) GetPayloadBodiesByHash(ctx context.Context, executionBlockHash return result, nil } err := s.rpcClient.CallContext(ctx, &result, GetPayloadBodiesByHashV1, executionBlockHashes) - + if err != nil { + return nil, handleRPCError(err) + } + if len(result) != len(executionBlockHashes) { + return nil, fmt.Errorf("mismatch of payloads retrieved from the execution client: %d vs %d", len(result), len(executionBlockHashes)) + } for i, item := range result { if item == nil { result[i] = &pb.ExecutionPayloadBodyV1{ @@ -502,7 +507,7 @@ func (s *Service) GetPayloadBodiesByHash(ctx context.Context, executionBlockHash } } } - return result, handleRPCError(err) + return result, nil } // GetPayloadBodiesByRange returns the relevant payload bodies for the provided range. @@ -635,6 +640,8 @@ func (s *Service) retrievePayloadFromExecutionHash(ctx context.Context, executio return fullPayloadFromPayloadBody(header, bdy, version) } +// 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, diff --git a/beacon-chain/execution/engine_client_test.go b/beacon-chain/execution/engine_client_test.go index 9a7002312edf..963ea8ef47a1 100644 --- a/beacon-chain/execution/engine_client_test.go +++ b/beacon-chain/execution/engine_client_test.go @@ -912,6 +912,73 @@ func TestReconstructFullBellatrixBlockBatch(t *testing.T) { require.NoError(t, err) require.DeepEqual(t, payload, got.Proto()) }) + t.Run("handles invalid response from EL", func(t *testing.T) { + fix := fixtures() + payload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload) + require.Equal(t, true, ok) + + jsonPayload := make(map[string]interface{}) + tx := gethtypes.NewTransaction( + 0, + common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), + big.NewInt(0), 0, big.NewInt(0), + nil, + ) + txs := []*gethtypes.Transaction{tx} + encodedBinaryTxs := make([][]byte, 1) + var err error + encodedBinaryTxs[0], err = txs[0].MarshalBinary() + require.NoError(t, err) + payload.Transactions = encodedBinaryTxs + jsonPayload["transactions"] = []hexutil.Bytes{encodedBinaryTxs[0]} + + wrappedPayload, err := blocks.WrappedExecutionPayload(payload) + require.NoError(t, err) + header, err := blocks.PayloadToHeader(wrappedPayload) + require.NoError(t, err) + + bellatrixBlock := util.NewBlindedBeaconBlockBellatrix() + wanted := util.NewBeaconBlockBellatrix() + wanted.Block.Slot = 1 + // Make sure block hash is the zero hash. + bellatrixBlock.Block.Body.ExecutionPayloadHeader.BlockHash = make([]byte, 32) + bellatrixBlock.Block.Slot = 1 + wrappedEmpty, err := blocks.NewSignedBeaconBlock(bellatrixBlock) + require.NoError(t, err) + + 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()) + }() + + respJSON := map[string]interface{}{ + "jsonrpc": "2.0", + "id": 1, + "result": []map[string]interface{}{}, + } + require.NoError(t, json.NewEncoder(w).Encode(respJSON)) + + })) + defer srv.Close() + + rpcClient, err := rpc.DialHTTP(srv.URL) + require.NoError(t, err) + defer rpcClient.Close() + + service := &Service{} + service.rpcClient = rpcClient + blindedBlock := util.NewBlindedBeaconBlockBellatrix() + + blindedBlock.Block.Body.ExecutionPayloadHeader = header + wrapped, err := blocks.NewSignedBeaconBlock(blindedBlock) + require.NoError(t, err) + copiedWrapped, err := wrapped.Copy() + require.NoError(t, err) + + _, err = service.ReconstructFullBellatrixBlockBatch(ctx, []interfaces.ReadOnlySignedBeaconBlock{wrappedEmpty, wrapped, copiedWrapped}) + require.ErrorContains(t, "mismatch of payloads retrieved from the execution client", err) + }) } func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) { @@ -2166,7 +2233,7 @@ func TestCapella_PayloadBodiesByHash(t *testing.T) { bRoot := [32]byte{} copy(bRoot[:], "hash") - results, err := service.GetPayloadBodiesByHash(ctx, []common.Hash{bRoot}) + results, err := service.GetPayloadBodiesByHash(ctx, []common.Hash{bRoot, bRoot}) require.NoError(t, err) require.Equal(t, 2, len(results))