Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion beacon-chain/execution/engine_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ func (s *Service) ForkchoiceUpdated(
func getPayloadMethodAndMessage(slot primitives.Slot) (string, proto.Message) {
pe := slots.ToEpoch(slot)
if pe >= params.BeaconConfig().FuluForkEpoch {
return GetPayloadMethodV5, &pb.ExecutionBundleElectra{}
return GetPayloadMethodV5, &pb.ExecutionBundleFulu{}
}
if pe >= params.BeaconConfig().ElectraForkEpoch {
return GetPayloadMethodV4, &pb.ExecutionBundleElectra{}
Expand Down
79 changes: 79 additions & 0 deletions beacon-chain/execution/engine_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ func TestClient_HTTP(t *testing.T) {
cfg.CapellaForkEpoch = 1
cfg.DenebForkEpoch = 2
cfg.ElectraForkEpoch = 3
cfg.FuluForkEpoch = 4
params.OverrideBeaconConfig(cfg)

t.Run(GetPayloadMethod, func(t *testing.T) {
Expand Down Expand Up @@ -406,7 +407,52 @@ func TestClient_HTTP(t *testing.T) {

require.DeepEqual(t, requests, resp.ExecutionRequests)
})
t.Run(GetPayloadMethodV5, func(t *testing.T) {
payloadId := [8]byte{1}
want, ok := fix["ExecutionBundleFulu"].(*pb.GetPayloadV5ResponseJson)
require.Equal(t, true, ok)
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())
}()
enc, err := io.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)

reqArg, err := json.Marshal(pb.PayloadIDBytes(payloadId))
require.NoError(t, err)

// We expect the JSON string RPC request contains the right arguments.
require.Equal(t, true, strings.Contains(
jsonRequestString, string(reqArg),
))
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": want,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
defer srv.Close()

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

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

// We call the RPC method via HTTP and expect a proper result.
resp, err := client.GetPayload(ctx, payloadId, 4*params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
_, ok = resp.BlobsBundle.(*pb.BlobsBundleV2)
if !ok {
t.Logf("resp.BlobsBundle has unexpected type: %T", resp.BlobsBundle)
}
require.Equal(t, ok, true)
})
t.Run(ForkchoiceUpdatedMethod+" VALID status", func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
HeadBlockHash: []byte("head"),
Expand Down Expand Up @@ -1540,6 +1586,7 @@ func fixtures() map[string]interface{} {
"ExecutionPayloadCapellaWithValue": s.ExecutionPayloadWithValueCapella,
"ExecutionPayloadDenebWithValue": s.ExecutionPayloadWithValueDeneb,
"ExecutionBundleElectra": s.ExecutionBundleElectra,
"ExecutionBundleFulu": s.ExecutionBundleFulu,
"ValidPayloadStatus": s.ValidPayloadStatus,
"InvalidBlockHashStatus": s.InvalidBlockHashStatus,
"AcceptedStatus": s.AcceptedStatus,
Expand Down Expand Up @@ -1775,6 +1822,36 @@ func fixturesStruct() *payloadFixtures {
append([]byte{pb.WithdrawalRequestType}, withdrawalRequestBytes...),
append([]byte{pb.ConsolidationRequestType}, consolidationRequestBytes...)},
}
executionBundleFixtureFulu := &pb.GetPayloadV5ResponseJson{
ShouldOverrideBuilder: true,
ExecutionPayload: &pb.ExecutionPayloadDenebJSON{
ParentHash: &common.Hash{'a'},
FeeRecipient: &common.Address{'b'},
StateRoot: &common.Hash{'c'},
ReceiptsRoot: &common.Hash{'d'},
LogsBloom: &hexutil.Bytes{'e'},
PrevRandao: &common.Hash{'f'},
BaseFeePerGas: "0x123",
BlockHash: &common.Hash{'g'},
Transactions: []hexutil.Bytes{{'h'}},
Withdrawals: []*pb.Withdrawal{},
BlockNumber: &hexUint,
GasLimit: &hexUint,
GasUsed: &hexUint,
Timestamp: &hexUint,
BlobGasUsed: &bgu,
ExcessBlobGas: &ebg,
},
BlockValue: "0x11fffffffff",
BlobsBundle: &pb.BlobBundleV2JSON{
Commitments: []hexutil.Bytes{[]byte("commitment1"), []byte("commitment2")},
Proofs: []hexutil.Bytes{[]byte("proof1"), []byte("proof2")},
Blobs: []hexutil.Bytes{{'a'}, {'b'}},
},
ExecutionRequests: []hexutil.Bytes{append([]byte{pb.DepositRequestType}, depositRequestBytes...),
append([]byte{pb.WithdrawalRequestType}, withdrawalRequestBytes...),
append([]byte{pb.ConsolidationRequestType}, consolidationRequestBytes...)},
}
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
sha3Uncles := bytesutil.PadTo([]byte("sha3Uncles"), fieldparams.RootLength)
miner := bytesutil.PadTo([]byte("miner"), fieldparams.FeeRecipientLength)
Expand Down Expand Up @@ -1869,6 +1946,7 @@ func fixturesStruct() *payloadFixtures {
ExecutionPayloadWithValueCapella: executionPayloadWithValueFixtureCapella,
ExecutionPayloadWithValueDeneb: executionPayloadWithValueFixtureDeneb,
ExecutionBundleElectra: executionBundleFixtureElectra,
ExecutionBundleFulu: executionBundleFixtureFulu,
ValidPayloadStatus: validStatus,
InvalidBlockHashStatus: inValidBlockHashStatus,
AcceptedStatus: acceptedStatus,
Expand All @@ -1893,6 +1971,7 @@ type payloadFixtures struct {
ExecutionPayloadWithValueCapella *pb.GetPayloadV2ResponseJson
ExecutionPayloadWithValueDeneb *pb.GetPayloadV3ResponseJson
ExecutionBundleElectra *pb.GetPayloadV4ResponseJson
ExecutionBundleFulu *pb.GetPayloadV5ResponseJson
ValidPayloadStatus *pb.PayloadStatus
InvalidBlockHashStatus *pb.PayloadStatus
AcceptedStatus *pb.PayloadStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package validator
import (
"fmt"

"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
Expand All @@ -12,9 +13,13 @@ import (
)

// constructGenericBeaconBlock constructs a `GenericBeaconBlock` based on the block version and other parameters.
func (vs *Server) constructGenericBeaconBlock(sBlk interfaces.SignedBeaconBlock, blobsBundle *enginev1.BlobsBundle, winningBid primitives.Wei) (*ethpb.GenericBeaconBlock, error) {
func (vs *Server) constructGenericBeaconBlock(
sBlk interfaces.SignedBeaconBlock,
blobsBundle enginev1.BlobsBundler,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blobsBundle ==> blobsBundler?
(To ensure consistency between variable name and type.)

winningBid primitives.Wei,
) (*ethpb.GenericBeaconBlock, error) {
if sBlk == nil || sBlk.Block() == nil {
return nil, fmt.Errorf("block cannot be nil")
return nil, errors.New("block cannot be nil")
}

blockProto, err := sBlk.Block().Proto()
Expand All @@ -34,12 +39,21 @@ func (vs *Server) constructGenericBeaconBlock(sBlk interfaces.SignedBeaconBlock,
return vs.constructBellatrixBlock(blockProto, isBlinded, bidStr), nil
case version.Capella:
return vs.constructCapellaBlock(blockProto, isBlinded, bidStr), nil
case version.Deneb:
return vs.constructDenebBlock(blockProto, isBlinded, bidStr, blobsBundle), nil
case version.Electra:
return vs.constructElectraBlock(blockProto, isBlinded, bidStr, blobsBundle), nil
case version.Deneb, version.Electra:
bundle, ok := blobsBundle.(*enginev1.BlobsBundle)
if blobsBundle != nil && !ok {
return nil, fmt.Errorf("expected *BlobsBundle, got %T", blobsBundle)
}
if sBlk.Version() == version.Deneb {
return vs.constructDenebBlock(blockProto, isBlinded, bidStr, bundle), nil
}
return vs.constructElectraBlock(blockProto, isBlinded, bidStr, bundle), nil
case version.Fulu:
return vs.constructFuluBlock(blockProto, isBlinded, bidStr, blobsBundle), nil
bundle, ok := blobsBundle.(*enginev1.BlobsBundleV2)
if blobsBundle != nil && !ok {
return nil, fmt.Errorf("expected *BlobsBundleV2, got %T", blobsBundle)
}
return vs.constructFuluBlock(blockProto, isBlinded, bidStr, bundle), nil
default:
return nil, fmt.Errorf("unknown block version: %d", sBlk.Version())
}
Expand Down Expand Up @@ -92,7 +106,7 @@ func (vs *Server) constructElectraBlock(blockProto proto.Message, isBlinded bool
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Electra{Electra: electraContents}, IsBlinded: false, PayloadValue: payloadValue}
}

func (vs *Server) constructFuluBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock {
func (vs *Server) constructFuluBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundleV2) *ethpb.GenericBeaconBlock {
if isBlinded {
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedFulu{BlindedFulu: blockProto.(*ethpb.BlindedBeaconBlockFulu)}, IsBlinded: true, PayloadValue: payloadValue}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,19 @@ func TestConstructGenericBeaconBlock(t *testing.T) {
require.NoError(t, err)
r1, err := eb.Block.HashTreeRoot()
require.NoError(t, err)
result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei())
bundle := &enginev1.BlobsBundleV2{
KzgCommitments: [][]byte{{1, 2, 3}},
Proofs: [][]byte{{4, 5, 6}},
Blobs: [][]byte{{7, 8, 9}},
}
result, err := vs.constructGenericBeaconBlock(b, bundle, primitives.ZeroWei())
require.NoError(t, err)
r2, err := result.GetFulu().Block.HashTreeRoot()
require.NoError(t, err)
require.Equal(t, r1, r2)
require.Equal(t, result.IsBlinded, false)
require.DeepEqual(t, bundle.Blobs, result.GetFulu().GetBlobs())
require.DeepEqual(t, bundle.Proofs, result.GetFulu().GetKzgProofs())
})

// Test for Electra version
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed
}()

winningBid := primitives.ZeroWei()
var bundle *enginev1.BlobsBundle
var bundle enginev1.BlobsBundler
if sBlk.Version() >= version.Bellatrix {
local, err := vs.getLocalPayload(ctx, sBlk.Block(), head)
if err != nil {
Expand Down Expand Up @@ -369,7 +369,7 @@ func (vs *Server) handleBlindedBlock(ctx context.Context, block interfaces.Signe
}

if isPeerDASEnabled {
dataColumnSideCars, err := peerdas.ConstructDataColumnSidecars(block, bundle.Blobs, bundle.Proofs)
dataColumnSideCars, err := peerdas.ConstructDataColumnSidecars(block, bundle.GetBlobs(), bundle.GetProofs())
if err != nil {
return nil, nil, nil, errors.Wrap(err, "construct data column sidecars")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const blockBuilderTimeout = 1 * time.Second
const gasLimitAdjustmentFactor = 1024

// Sets the execution data for the block. Execution data can come from local EL client or remote builder depends on validator registration and circuit breaker conditions.
func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, local *blocks.GetPayloadResponse, bid builder.Bid, builderBoostFactor primitives.Gwei) (primitives.Wei, *enginev1.BlobsBundle, error) {
func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, local *blocks.GetPayloadResponse, bid builder.Bid, builderBoostFactor primitives.Gwei) (primitives.Wei, enginev1.BlobsBundler, error) {
_, span := trace.StartSpan(ctx, "ProposerServer.setExecutionData")
defer span.End()

Expand Down Expand Up @@ -376,7 +376,7 @@ func matchingWithdrawalsRoot(local, builder interfaces.ExecutionData) (bool, err
func setLocalExecution(blk interfaces.SignedBeaconBlock, local *blocks.GetPayloadResponse) error {
var kzgCommitments [][]byte
if local.BlobsBundle != nil {
kzgCommitments = local.BlobsBundle.KzgCommitments
kzgCommitments = local.BlobsBundle.GetKzgCommitments()
}
if local.ExecutionRequests != nil {
if err := blk.SetExecutionRequests(local.ExecutionRequests); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions consensus-types/blocks/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func NewWrappedExecutionData(v proto.Message) (interfaces.ExecutionData, error)
case *enginev1.ExecutionBundleElectra:
// note: no payload changes in electra so using deneb
return WrappedExecutionPayloadDeneb(pbStruct.Payload)
case *enginev1.ExecutionBundleFulu:
return WrappedExecutionPayloadDeneb(pbStruct.Payload)
default:
// return nil, errors.Wrapf(ErrUnsupportedVersion, "type %T", pbStruct)
return nil, errs.Wrapf(ErrUnsupportedVersion, "type %T", pbStruct)
Expand Down
10 changes: 9 additions & 1 deletion consensus-types/blocks/get_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// GetPayloadResponseV(1|2|3|4) value.
type GetPayloadResponse struct {
ExecutionData interfaces.ExecutionData
BlobsBundle *pb.BlobsBundle
BlobsBundle pb.BlobsBundler
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BlobsBundle ==> BlobsBundler?
(To ensure struct field consistency with type.)

OverrideBuilder bool
// todo: should we convert this to Gwei up front?
Bid primitives.Wei
Expand All @@ -24,6 +24,10 @@ type bundleGetter interface {
GetBlobsBundle() *pb.BlobsBundle
}

type bundleV2Getter interface {
GetBlobsBundle() *pb.BlobsBundleV2
}

// bidValueGetter is an interface satisfied by get payload responses that have a bid value.
type bidValueGetter interface {
GetValue() []byte
Expand All @@ -43,6 +47,10 @@ func NewGetPayloadResponse(msg proto.Message) (*GetPayloadResponse, error) {
if hasBundle {
r.BlobsBundle = bundleGetter.GetBlobsBundle()
}
bundleV2Getter, hasBundle := msg.(bundleV2Getter)
if hasBundle {
r.BlobsBundle = bundleV2Getter.GetBlobsBundle()
}
bidValueGetter, hasBid := msg.(bidValueGetter)
executionRequestsGetter, hasExecutionRequests := msg.(executionRequestsGetter)
wei := primitives.ZeroWei()
Expand Down
1 change: 1 addition & 0 deletions proto/engine/v1/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ go_proto_library(
go_library(
name = "go_default_library",
srcs = [
"blobs_bundle.go",
"electra.go",
"execution_engine.go",
"json_marshal_unmarshal.go",
Expand Down
7 changes: 7 additions & 0 deletions proto/engine/v1/blobs_bundle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package enginev1

type BlobsBundler interface {
GetKzgCommitments() [][]byte
GetProofs() [][]byte
GetBlobs() [][]byte
}
Loading
Loading