Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add deneb support for type conversions #496

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ linters-settings:
#
# Easier to read with only one of the versioned payloads.
#
- 'VersionedSubmitBlindedBlockResponse'
- 'VersionedExecutionPayload'
- 'VersionedSignedBuilderBid'

Expand Down
249 changes: 152 additions & 97 deletions common/types_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
apiv1deneb "github.com/attestantio/go-eth2-client/api/v1/deneb"
consensusspec "github.com/attestantio/go-eth2-client/spec"
consensuscapella "github.com/attestantio/go-eth2-client/spec/capella"
consensusdeneb "github.com/attestantio/go-eth2-client/spec/deneb"
"github.com/attestantio/go-eth2-client/spec/phase0"
utilbellatrix "github.com/attestantio/go-eth2-client/util/bellatrix"
utilcapella "github.com/attestantio/go-eth2-client/util/capella"
utildeneb "github.com/attestantio/go-eth2-client/util/deneb"
"github.com/flashbots/go-boost-utils/bls"
"github.com/flashbots/go-boost-utils/ssz"
boostTypes "github.com/flashbots/go-boost-utils/types"
Expand Down Expand Up @@ -48,23 +48,46 @@ func BuildGetHeaderResponse(payload *VersionedSubmitBlockRequest, sk *bls.Secret
return nil, ErrMissingSecretKey
}

if payload.Capella != nil {
signedBuilderBid, err := CapellaBuilderSubmitBlockRequestToSignedBuilderBid(payload.Capella, sk, pubkey, domain)
versionedPayload := &api.VersionedExecutionPayload{Version: payload.Version}
switch payload.Version {
case consensusspec.DataVersionCapella:
versionedPayload.Capella = payload.Capella.ExecutionPayload
header, err := utils.PayloadToPayloadHeader(versionedPayload)
if err != nil {
return nil, err
}
signedBuilderBid, err := BuilderBlockRequestToSignedBuilderBid(payload, header, sk, pubkey, domain)
if err != nil {
return nil, err
}
return &spec.VersionedSignedBuilderBid{
Version: consensusspec.DataVersionCapella,
Capella: signedBuilderBid,
Bellatrix: nil,
Version: consensusspec.DataVersionCapella,
Capella: signedBuilderBid.Capella,
}, nil
case consensusspec.DataVersionDeneb:
versionedPayload.Deneb = payload.Deneb.ExecutionPayload
header, err := utils.PayloadToPayloadHeader(versionedPayload)
if err != nil {
return nil, err
}
signedBuilderBid, err := BuilderBlockRequestToSignedBuilderBid(payload, header, sk, pubkey, domain)
if err != nil {
return nil, err
}
return &spec.VersionedSignedBuilderBid{
Version: consensusspec.DataVersionDeneb,
Deneb: signedBuilderBid.Deneb,
}, nil
case consensusspec.DataVersionUnknown, consensusspec.DataVersionPhase0, consensusspec.DataVersionAltair, consensusspec.DataVersionBellatrix:
return nil, ErrInvalidVersion
default:
return nil, ErrEmptyPayload
}
return nil, ErrEmptyPayload
}

func BuildGetPayloadResponse(payload *VersionedSubmitBlockRequest) (*api.VersionedExecutionPayload, error) {
func BuildGetPayloadResponse(payload *VersionedSubmitBlockRequest) (*api.VersionedSubmitBlindedBlockResponse, error) {
if payload.Capella != nil {
return &api.VersionedExecutionPayload{
return &api.VersionedSubmitBlindedBlockResponse{
Version: consensusspec.DataVersionCapella,
Capella: payload.Capella.ExecutionPayload,
}, nil
Expand All @@ -73,19 +96,14 @@ func BuildGetPayloadResponse(payload *VersionedSubmitBlockRequest) (*api.Version
return nil, ErrEmptyPayload
}

func BuilderSubmitBlockRequestToSignedBuilderBid(req *VersionedSubmitBlockRequest, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*spec.VersionedSignedBuilderBid, error) {
value, err := req.Value()
func BuilderBlockRequestToSignedBuilderBid(payload *VersionedSubmitBlockRequest, header *api.VersionedExecutionPayloadHeader, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*spec.VersionedSignedBuilderBid, error) {
value, err := payload.Value()
if err != nil {
return nil, err
}

switch req.Version {
switch payload.Version {
case consensusspec.DataVersionCapella:
header, err := utils.PayloadToPayloadHeader(&api.VersionedExecutionPayload{Version: req.Version, Capella: req.Capella.ExecutionPayload})
if err != nil {
return nil, err
}

builderBid := capella.BuilderBid{
Value: value,
Header: header.Capella,
Expand All @@ -104,100 +122,137 @@ func BuilderSubmitBlockRequestToSignedBuilderBid(req *VersionedSubmitBlockReques
Signature: sig,
},
}, nil
case consensusspec.DataVersionUnknown, consensusspec.DataVersionPhase0, consensusspec.DataVersionAltair, consensusspec.DataVersionBellatrix, consensusspec.DataVersionDeneb:
return nil, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%s is not supported", req.Version.String()))
default:
return nil, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%s is not supported", req.Version.String()))
}
}
case consensusspec.DataVersionDeneb:
var blobRoots []phase0.Root
for i, blob := range payload.Deneb.BlobsBundle.Blobs {
blobRootHelper := utildeneb.BeaconBlockBlob{Blob: blob}
root, err := blobRootHelper.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("failed to calculate blob root at blob index %d", i))
}
blobRoots = append(blobRoots, root)
}
blindedBlobRoots := deneb.BlindedBlobsBundle{
Commitments: payload.Deneb.BlobsBundle.Commitments,
Proofs: payload.Deneb.BlobsBundle.Proofs,
BlobRoots: blobRoots,
}

func CapellaBuilderSubmitBlockRequestToSignedBuilderBid(req *capella.SubmitBlockRequest, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*capella.SignedBuilderBid, error) {
header, err := CapellaPayloadToPayloadHeader(req.ExecutionPayload)
if err != nil {
return nil, err
}
builderBid := deneb.BuilderBid{
Value: value,
Header: header.Deneb,
BlindedBlobsBundle: &blindedBlobRoots,
Pubkey: *pubkey,
}

builderBid := capella.BuilderBid{
Value: req.Message.Value,
Header: header,
Pubkey: *pubkey,
}
sig, err := ssz.SignMessage(&builderBid, domain, sk)
if err != nil {
return nil, err
}

sig, err := ssz.SignMessage(&builderBid, domain, sk)
if err != nil {
return nil, err
return &spec.VersionedSignedBuilderBid{
Version: consensusspec.DataVersionDeneb,
Deneb: &deneb.SignedBuilderBid{
Message: &builderBid,
Signature: sig,
},
}, nil
case consensusspec.DataVersionUnknown, consensusspec.DataVersionPhase0, consensusspec.DataVersionAltair, consensusspec.DataVersionBellatrix:
fallthrough
default:
return nil, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%s is not supported", payload.Version.String()))
}

return &capella.SignedBuilderBid{
Message: &builderBid,
Signature: sig,
}, nil
}

func CapellaPayloadToPayloadHeader(p *consensuscapella.ExecutionPayload) (*consensuscapella.ExecutionPayloadHeader, error) {
if p == nil {
return nil, ErrEmptyPayload
func SignedBlindedBeaconBlockToBeaconBlock(signedBlindedBeaconBlock *VersionedSignedBlindedBlockRequest, blockPayload *api.VersionedSubmitBlindedBlockResponse) (*VersionedSignedBlockRequest, error) {
signedBeaconBlock := VersionedSignedBlockRequest{
consensusapi.VersionedBlockRequest{ //nolint:exhaustruct
Version: signedBlindedBeaconBlock.Version,
},
}

transactions := utilbellatrix.ExecutionPayloadTransactions{Transactions: p.Transactions}
transactionsRoot, err := transactions.HashTreeRoot()
if err != nil {
return nil, err
switch signedBlindedBeaconBlock.Version {
case consensusspec.DataVersionCapella:
capellaBlindedBlock := signedBlindedBeaconBlock.Capella
signedBeaconBlock.Capella = CapellaUnblindSignedBlock(capellaBlindedBlock, blockPayload.Capella)
case consensusspec.DataVersionDeneb:
denebBlindedBlock := signedBlindedBeaconBlock.Deneb.SignedBlindedBlock
blockRoot, err := denebBlindedBlock.Message.HashTreeRoot()
if err != nil {
return nil, err
}
signedBeaconBlock.Deneb = DenebUnblindSignedBlock(denebBlindedBlock, blockPayload.Deneb, blockRoot)
case consensusspec.DataVersionUnknown, consensusspec.DataVersionPhase0, consensusspec.DataVersionAltair, consensusspec.DataVersionBellatrix:
return nil, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%s is not supported", signedBlindedBeaconBlock.Version.String()))
}
return &signedBeaconBlock, nil
}

withdrawals := utilcapella.ExecutionPayloadWithdrawals{Withdrawals: p.Withdrawals}
withdrawalsRoot, err := withdrawals.HashTreeRoot()
if err != nil {
return nil, err
func CapellaUnblindSignedBlock(blindedBlock *apiv1capella.SignedBlindedBeaconBlock, executionPayload *consensuscapella.ExecutionPayload) *consensuscapella.SignedBeaconBlock {
return &consensuscapella.SignedBeaconBlock{
Signature: blindedBlock.Signature,
Message: &consensuscapella.BeaconBlock{
Slot: blindedBlock.Message.Slot,
ProposerIndex: blindedBlock.Message.ProposerIndex,
ParentRoot: blindedBlock.Message.ParentRoot,
StateRoot: blindedBlock.Message.StateRoot,
Body: &consensuscapella.BeaconBlockBody{
BLSToExecutionChanges: blindedBlock.Message.Body.BLSToExecutionChanges,
RANDAOReveal: blindedBlock.Message.Body.RANDAOReveal,
ETH1Data: blindedBlock.Message.Body.ETH1Data,
Graffiti: blindedBlock.Message.Body.Graffiti,
ProposerSlashings: blindedBlock.Message.Body.ProposerSlashings,
AttesterSlashings: blindedBlock.Message.Body.AttesterSlashings,
Attestations: blindedBlock.Message.Body.Attestations,
Deposits: blindedBlock.Message.Body.Deposits,
VoluntaryExits: blindedBlock.Message.Body.VoluntaryExits,
SyncAggregate: blindedBlock.Message.Body.SyncAggregate,
ExecutionPayload: executionPayload,
},
},
}

return &consensuscapella.ExecutionPayloadHeader{
ParentHash: p.ParentHash,
FeeRecipient: p.FeeRecipient,
StateRoot: p.StateRoot,
ReceiptsRoot: p.ReceiptsRoot,
LogsBloom: p.LogsBloom,
PrevRandao: p.PrevRandao,
BlockNumber: p.BlockNumber,
GasLimit: p.GasLimit,
GasUsed: p.GasUsed,
Timestamp: p.Timestamp,
ExtraData: p.ExtraData,
BaseFeePerGas: p.BaseFeePerGas,
BlockHash: p.BlockHash,
TransactionsRoot: transactionsRoot,
WithdrawalsRoot: withdrawalsRoot,
}, nil
}

func SignedBlindedBeaconBlockToBeaconBlock(signedBlindedBeaconBlock *VersionedSignedBlindedBlockRequest, executionPayload *api.VersionedExecutionPayload) *VersionedSignedBlockRequest {
var signedBeaconBlock VersionedSignedBlockRequest
capellaBlindedBlock := signedBlindedBeaconBlock.Capella
if capellaBlindedBlock != nil {
signedBeaconBlock.Capella = &consensuscapella.SignedBeaconBlock{
Signature: capellaBlindedBlock.Signature,
Message: &consensuscapella.BeaconBlock{
Slot: capellaBlindedBlock.Message.Slot,
ProposerIndex: capellaBlindedBlock.Message.ProposerIndex,
ParentRoot: capellaBlindedBlock.Message.ParentRoot,
StateRoot: capellaBlindedBlock.Message.StateRoot,
Body: &consensuscapella.BeaconBlockBody{
BLSToExecutionChanges: capellaBlindedBlock.Message.Body.BLSToExecutionChanges,
RANDAOReveal: capellaBlindedBlock.Message.Body.RANDAOReveal,
ETH1Data: capellaBlindedBlock.Message.Body.ETH1Data,
Graffiti: capellaBlindedBlock.Message.Body.Graffiti,
ProposerSlashings: capellaBlindedBlock.Message.Body.ProposerSlashings,
AttesterSlashings: capellaBlindedBlock.Message.Body.AttesterSlashings,
Attestations: capellaBlindedBlock.Message.Body.Attestations,
Deposits: capellaBlindedBlock.Message.Body.Deposits,
VoluntaryExits: capellaBlindedBlock.Message.Body.VoluntaryExits,
SyncAggregate: capellaBlindedBlock.Message.Body.SyncAggregate,
ExecutionPayload: executionPayload.Capella,
func DenebUnblindSignedBlock(blindedBlock *apiv1deneb.SignedBlindedBeaconBlock, blockPayload *deneb.ExecutionPayloadAndBlobsBundle, blockRoot phase0.Root) *apiv1deneb.SignedBlockContents {
denebBlobSidecars := make([]*consensusdeneb.BlobSidecar, len(blockPayload.BlobsBundle.Blobs))

for i := range denebBlobSidecars {
denebBlobSidecars[i] = &consensusdeneb.BlobSidecar{
BlockRoot: blockRoot,
Index: consensusdeneb.BlobIndex(i),
Slot: blindedBlock.Message.Slot,
BlockParentRoot: blindedBlock.Message.ParentRoot,
ProposerIndex: blindedBlock.Message.ProposerIndex,
Blob: blockPayload.BlobsBundle.Blobs[i],
KzgCommitment: blockPayload.BlobsBundle.Commitments[i],
KzgProof: blockPayload.BlobsBundle.Proofs[i],
}
}
return &apiv1deneb.SignedBlockContents{
Message: &apiv1deneb.BlockContents{
Block: &consensusdeneb.BeaconBlock{
Slot: blindedBlock.Message.Slot,
ProposerIndex: blindedBlock.Message.ProposerIndex,
ParentRoot: blindedBlock.Message.ParentRoot,
StateRoot: blindedBlock.Message.StateRoot,
Body: &consensusdeneb.BeaconBlockBody{
BLSToExecutionChanges: blindedBlock.Message.Body.BLSToExecutionChanges,
RANDAOReveal: blindedBlock.Message.Body.RANDAOReveal,
ETH1Data: blindedBlock.Message.Body.ETH1Data,
Graffiti: blindedBlock.Message.Body.Graffiti,
ProposerSlashings: blindedBlock.Message.Body.ProposerSlashings,
AttesterSlashings: blindedBlock.Message.Body.AttesterSlashings,
Attestations: blindedBlock.Message.Body.Attestations,
Deposits: blindedBlock.Message.Body.Deposits,
VoluntaryExits: blindedBlock.Message.Body.VoluntaryExits,
SyncAggregate: blindedBlock.Message.Body.SyncAggregate,
ExecutionPayload: blockPayload.ExecutionPayload,
BlobKzgCommitments: blockPayload.BlobsBundle.Commitments,
},
},
}
BlobSidecars: denebBlobSidecars,
},
Signature: blindedBlock.Signature,
}
return &signedBeaconBlock
}

type BuilderBlockValidationRequest struct {
Expand Down
20 changes: 16 additions & 4 deletions common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

"github.com/attestantio/go-builder-client/api"
"github.com/attestantio/go-builder-client/api/capella"
"github.com/attestantio/go-builder-client/api/deneb"
apiv1 "github.com/attestantio/go-builder-client/api/v1"
"github.com/attestantio/go-builder-client/spec"
consensusspec "github.com/attestantio/go-eth2-client/spec"
Expand Down Expand Up @@ -185,7 +186,7 @@ type CreateTestBlockSubmissionOpts struct {
ProposerPubkey string
}

func CreateTestBlockSubmission(t *testing.T, builderPubkey string, value *uint256.Int, opts *CreateTestBlockSubmissionOpts) (payload *VersionedSubmitBlockRequest, getPayloadResponse *api.VersionedExecutionPayload, getHeaderResponse *spec.VersionedSignedBuilderBid) {
func CreateTestBlockSubmission(t *testing.T, builderPubkey string, value *uint256.Int, opts *CreateTestBlockSubmissionOpts) (payload *VersionedSubmitBlockRequest, getPayloadResponse *api.VersionedSubmitBlindedBlockResponse, getHeaderResponse *spec.VersionedSignedBuilderBid) {
t.Helper()
var err error

Expand Down Expand Up @@ -349,12 +350,23 @@ func GetBlockSubmissionInfo(submission *VersionedSubmitBlockRequest) (*BlockSubm
}, nil
}

func GetBlockSubmissionExecutionPayload(submission *VersionedSubmitBlockRequest) (*api.VersionedExecutionPayload, error) {
if submission.Capella != nil {
return &api.VersionedExecutionPayload{
func GetBlockSubmissionExecutionPayload(submission *VersionedSubmitBlockRequest) (*api.VersionedSubmitBlindedBlockResponse, error) {
switch submission.Version {
case consensusspec.DataVersionCapella:
return &api.VersionedSubmitBlindedBlockResponse{
Version: consensusspec.DataVersionCapella,
Capella: submission.Capella.ExecutionPayload,
}, nil
case consensusspec.DataVersionDeneb:
return &api.VersionedSubmitBlindedBlockResponse{
Version: consensusspec.DataVersionDeneb,
Deneb: &deneb.ExecutionPayloadAndBlobsBundle{
ExecutionPayload: submission.Deneb.ExecutionPayload,
BlobsBundle: submission.Deneb.BlobsBundle,
},
}, nil
case consensusspec.DataVersionUnknown, consensusspec.DataVersionPhase0, consensusspec.DataVersionAltair, consensusspec.DataVersionBellatrix:
return nil, ErrInvalidForkVersion
}
return nil, ErrEmptyPayload
}
Loading
Loading