Skip to content

Commit

Permalink
add conversion functions
Browse files Browse the repository at this point in the history
  • Loading branch information
avalonche committed May 3, 2024
1 parent fe73df7 commit f01beea
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 1 deletion.
86 changes: 86 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
var (
ErrUnknownNetwork = errors.New("unknown network")
ErrEmptyPayload = errors.New("empty payload")
ErrEmptyPayloadHeader = errors.New("empty payload header")
ErrEmptyPayloadMessage = errors.New("empty payload message")
ErrVersionNotSupported = errors.New("version is not supported")

EthNetworkHolesky = "holesky"
Expand Down Expand Up @@ -418,6 +420,15 @@ type BlockSubmissionInfo struct {
ExcessBlobGas uint64
}

type HeaderSubmissionInfo struct {
BidTrace *builderApiV1.BidTrace
Signature phase0.BLSSignature
Timestamp uint64
PrevRandao phase0.Hash32
TransactionsRoot phase0.Root
WithdrawalsRoot phase0.Root
}

// VersionedSubmitHeaderOptimistic is a versioned signed header to construct the builder bid.
type VersionedSubmitHeaderOptimistic struct {
Version spec.DataVersion
Expand Down Expand Up @@ -467,6 +478,12 @@ func (h *VersionedSubmitHeaderOptimistic) UnmarshalJSON(data []byte) error {
func (h *VersionedSubmitHeaderOptimistic) BidTrace() (*builderApiV1.BidTrace, error) {
switch h.Version { //nolint:exhaustive
case spec.DataVersionDeneb:
if h.Deneb == nil {
return nil, ErrEmptyPayload
}
if h.Deneb.Message == nil {
return nil, ErrEmptyPayloadMessage
}
return h.Deneb.Message, nil
default:
return nil, fmt.Errorf("%w: %s", ErrVersionNotSupported, h.Version)
Expand All @@ -476,6 +493,12 @@ func (h *VersionedSubmitHeaderOptimistic) BidTrace() (*builderApiV1.BidTrace, er
func (h *VersionedSubmitHeaderOptimistic) ExecutionPayloadBlockHash() (phase0.Hash32, error) {
switch h.Version { //nolint:exhaustive
case spec.DataVersionDeneb:
if h.Deneb == nil {
return phase0.Hash32{}, ErrEmptyPayload
}
if h.Deneb.ExecutionPayloadHeader == nil {
return phase0.Hash32{}, ErrEmptyPayloadHeader
}
return h.Deneb.ExecutionPayloadHeader.BlockHash, nil
default:
return phase0.Hash32{}, fmt.Errorf("%w: %s", ErrVersionNotSupported, h.Version)
Expand All @@ -485,12 +508,75 @@ func (h *VersionedSubmitHeaderOptimistic) ExecutionPayloadBlockHash() (phase0.Ha
func (h *VersionedSubmitHeaderOptimistic) Signature() (phase0.BLSSignature, error) {
switch h.Version { //nolint:exhaustive
case spec.DataVersionDeneb:
if h.Deneb == nil {
return phase0.BLSSignature{}, ErrEmptyPayload
}
return h.Deneb.Signature, nil
default:
return phase0.BLSSignature{}, fmt.Errorf("%w: %s", ErrVersionNotSupported, h.Version)
}
}

func (h *VersionedSubmitHeaderOptimistic) Timestamp() (uint64, error) {
switch h.Version { //nolint:exhaustive
case spec.DataVersionDeneb:
if h.Deneb == nil {
return 0, ErrEmptyPayload
}
if h.Deneb.ExecutionPayloadHeader == nil {
return 0, ErrEmptyPayloadHeader
}
return h.Deneb.ExecutionPayloadHeader.Timestamp, nil
default:
return 0, fmt.Errorf("%w: %s", ErrVersionNotSupported, h.Version)
}
}

func (h *VersionedSubmitHeaderOptimistic) PrevRandao() (phase0.Hash32, error) {
switch h.Version { //nolint:exhaustive
case spec.DataVersionDeneb:
if h.Deneb == nil {
return phase0.Hash32{}, ErrEmptyPayload
}
if h.Deneb.ExecutionPayloadHeader == nil {
return phase0.Hash32{}, ErrEmptyPayloadHeader
}
return h.Deneb.ExecutionPayloadHeader.PrevRandao, nil
default:
return phase0.Hash32{}, fmt.Errorf("%w: %s", ErrVersionNotSupported, h.Version)
}
}

func (h *VersionedSubmitHeaderOptimistic) TransactionsRoot() (phase0.Root, error) {
switch h.Version { //nolint:exhaustive
case spec.DataVersionDeneb:
if h.Deneb == nil {
return phase0.Root{}, ErrEmptyPayload
}
if h.Deneb.ExecutionPayloadHeader == nil {
return phase0.Root{}, ErrEmptyPayloadHeader
}
return h.Deneb.ExecutionPayloadHeader.TransactionsRoot, nil
default:
return phase0.Root{}, fmt.Errorf("%w: %s", ErrVersionNotSupported, h.Version)
}
}

func (h *VersionedSubmitHeaderOptimistic) WithdrawalsRoot() (phase0.Root, error) {
switch h.Version { //nolint:exhaustive
case spec.DataVersionDeneb:
if h.Deneb == nil {
return phase0.Root{}, ErrEmptyPayload
}
if h.Deneb.ExecutionPayloadHeader == nil {
return phase0.Root{}, ErrEmptyPayloadHeader
}
return h.Deneb.ExecutionPayloadHeader.WithdrawalsRoot, nil
default:
return phase0.Root{}, fmt.Errorf("%w: %s", ErrVersionNotSupported, h.Version)
}
}

/*
DenebSubmitHeaderOptimistic is request from the builder to submit a Deneb header. At minimum
without blobs, it is 956 bytes. With the current maximum of 6 blobs this adds another 288
Expand Down
37 changes: 37 additions & 0 deletions common/types_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,43 @@ func BuildGetPayloadResponse(payload *VersionedSubmitBlockRequest) (*builderApi.
return nil, ErrEmptyPayload
}

func BuildGetHeaderResponseOptimistic(payload *VersionedSubmitHeaderOptimistic, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*builderSpec.VersionedSignedBuilderBid, error) {
if payload == nil {
return nil, ErrMissingRequest
}

if sk == nil {
return nil, ErrMissingSecretKey
}

switch payload.Version {
case spec.DataVersionDeneb:
builderBid := builderApiDeneb.BuilderBid{
Header: payload.Deneb.ExecutionPayloadHeader,
BlobKZGCommitments: payload.Deneb.BlobKZGCommitments,
Value: payload.Deneb.Message.Value,
Pubkey: *pubkey,
}

sig, err := ssz.SignMessage(&builderBid, domain, sk)
if err != nil {
return nil, err
}

return &builderSpec.VersionedSignedBuilderBid{
Version: spec.DataVersionDeneb,
Deneb: &builderApiDeneb.SignedBuilderBid{
Message: &builderBid,
Signature: sig,
},
}, nil
case spec.DataVersionUnknown, spec.DataVersionPhase0, spec.DataVersionAltair, spec.DataVersionBellatrix, spec.DataVersionCapella:
return nil, ErrInvalidVersion
default:
return nil, ErrEmptyPayload
}
}

func BuilderBlockRequestToSignedBuilderBid(payload *VersionedSubmitBlockRequest, header *builderApi.VersionedExecutionPayloadHeader, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*builderSpec.VersionedSignedBuilderBid, error) {
value, err := payload.Value()
if err != nil {
Expand Down
35 changes: 35 additions & 0 deletions common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,41 @@ func GetBlockSubmissionInfo(submission *VersionedSubmitBlockRequest) (*BlockSubm
}, nil
}

func GetHeaderSubmissionInfo(submission *VersionedSubmitHeaderOptimistic) (*HeaderSubmissionInfo, error) {
bidTrace, err := submission.BidTrace()
if err != nil {
return nil, err
}
signature, err := submission.Signature()
if err != nil {
return nil, err
}
timestamp, err := submission.Timestamp()
if err != nil {
return nil, err
}
prevRandao, err := submission.PrevRandao()
if err != nil {
return nil, err
}
transactionsRoot, err := submission.TransactionsRoot()
if err != nil {
return nil, err
}
withdrawalsRoot, err := submission.WithdrawalsRoot()
if err != nil {
return nil, err
}
return &HeaderSubmissionInfo{
BidTrace: bidTrace,
Signature: signature,
Timestamp: timestamp,
PrevRandao: prevRandao,
TransactionsRoot: transactionsRoot,
WithdrawalsRoot: withdrawalsRoot,
}, nil
}

func GetBlockSubmissionExecutionPayload(submission *VersionedSubmitBlockRequest) (*builderApi.VersionedSubmitBlindedBlockResponse, error) {
switch submission.Version {
case spec.DataVersionCapella:
Expand Down
76 changes: 75 additions & 1 deletion common/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/bellatrix"
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/attestantio/go-eth2-client/spec/deneb"
"github.com/ethereum/go-ethereum/common"
boostTypes "github.com/flashbots/go-boost-utils/types"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -114,7 +115,7 @@ func TestGetBlockSubmissionInfo(t *testing.T) {
err string
}{
{
name: "valid builderApiCapella",
name: "valid capella",
payload: &VersionedSubmitBlockRequest{
VersionedSubmitBlockRequest: builderSpec.VersionedSubmitBlockRequest{
Version: spec.DataVersionCapella,
Expand Down Expand Up @@ -192,3 +193,76 @@ func TestGetBlockSubmissionInfo(t *testing.T) {
})
}
}

func TestGetHeaderSubmissionInfo(t *testing.T) {
cases := []struct {
name string
payload *VersionedSubmitHeaderOptimistic
expected *HeaderSubmissionInfo
err string
}{
{
name: "valid deneb",
payload: &VersionedSubmitHeaderOptimistic{
Version: spec.DataVersionDeneb,
Deneb: &DenebSubmitHeaderOptimistic{
Message: &builderApiV1.BidTrace{},
ExecutionPayloadHeader: &deneb.ExecutionPayloadHeader{},
},
},
expected: &HeaderSubmissionInfo{
BidTrace: &builderApiV1.BidTrace{},
},
},
{
name: "unsupported version",
payload: &VersionedSubmitHeaderOptimistic{
Version: spec.DataVersionCapella,
},
expected: nil,
err: "version is not supported: capella",
},
{
name: "missing data",
payload: &VersionedSubmitHeaderOptimistic{
Version: spec.DataVersionDeneb,
},
expected: nil,
err: "no data",
},
{
name: "missing message",
payload: &VersionedSubmitHeaderOptimistic{
Version: spec.DataVersionDeneb,
Deneb: &DenebSubmitHeaderOptimistic{
ExecutionPayloadHeader: &deneb.ExecutionPayloadHeader{},
},
},
expected: nil,
err: "no data message",
},
{
name: "missing execution payload",
payload: &VersionedSubmitHeaderOptimistic{
Version: spec.DataVersionDeneb,
Deneb: &DenebSubmitHeaderOptimistic{
Message: &builderApiV1.BidTrace{},
},
},
expected: nil,
err: "no data execution payload header",
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
submission, err := GetHeaderSubmissionInfo(tc.payload)
require.Equal(t, tc.expected, submission)
if tc.err == "" {
require.NoError(t, err)
} else {
require.Equal(t, tc.err, err.Error())
}
})
}
}

0 comments on commit f01beea

Please sign in to comment.