Skip to content
Merged
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
34 changes: 16 additions & 18 deletions core/validatorapi/mocks/handler.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 25 additions & 15 deletions core/validatorapi/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ type Handler interface {
eth2client.BeaconCommitteeSelectionsProvider
eth2client.BlindedProposalSubmitter
eth2client.NodeVersionProvider
eth2client.PayloadAttestationDataProvider
eth2client.PayloadAttestationMessagesSubmitter
eth2client.ProposerDutiesProvider
eth2client.SyncCommitteeContributionProvider
eth2client.SyncCommitteeContributionsSubmitter
Expand All @@ -89,15 +91,6 @@ type Handler interface {
eth2client.VoluntaryExitSubmitter
// Above sorted alphabetically.

// TODO(gloas): replace with eth2client.PayloadAttestationDataProvider and
// eth2client.PayloadAttestationMessagesSubmitter once go-eth2-client exposes them
// (attestantio/go-eth2-client#311).

// PayloadAttestationData returns the payload attestation data for the provided slot.
PayloadAttestationData(ctx context.Context, slot uint64) (*gloas.PayloadAttestationData, error)
// SubmitPayloadAttestationMessages receives partially signed payload attestation messages.
SubmitPayloadAttestationMessages(ctx context.Context, messages []*gloas.PayloadAttestationMessage) error

// Address returns the address of the beacon node.
Address() string
// Headers returns custom headers to include in requests to the beacon node.
Expand Down Expand Up @@ -1606,32 +1599,41 @@ func submitAggregateAttestations(s eth2client.AggregateAttestationsSubmitter) ha
}

// payloadAttestationData returns a handler function for the payload attestation data endpoint.
func payloadAttestationData(h Handler) handlerFunc {
func payloadAttestationData(p eth2client.PayloadAttestationDataProvider) handlerFunc {
return func(ctx context.Context, _ map[string]string, _ http.Header, query url.Values, _ contentType, _ []byte) (any, http.Header, error) {
slot, err := uintQuery(query, "slot")
if err != nil {
return nil, nil, err
}

data, err := h.PayloadAttestationData(ctx, slot)
opts := &eth2api.PayloadAttestationDataOpts{
Slot: eth2p0.Slot(slot),
}

eth2Resp, err := p.PayloadAttestationData(ctx, opts)
if err != nil {
return nil, nil, err
}

version := eth2spec.DataVersionGloas.String()
data := eth2Resp.Data
if data.Version != eth2spec.DataVersionGloas || data.Gloas == nil {
return nil, nil, errors.New("unsupported payload attestation data version")
}

version := data.Version.String()
Comment thread
KaloyanTanev marked this conversation as resolved.

return struct {
Version string `json:"version"`
Data *gloas.PayloadAttestationData `json:"data"`
}{
Version: version,
Data: data,
Data: data.Gloas,
}, http.Header{versionHeader: []string{version}}, nil
}
}

// submitPayloadAttestationMessages returns a handler function for the payload attestation pool submission endpoint.
func submitPayloadAttestationMessages(h Handler) handlerFunc {
func submitPayloadAttestationMessages(s eth2client.PayloadAttestationMessagesSubmitter) handlerFunc {
return func(ctx context.Context, _ map[string]string, header http.Header, _ url.Values, typ contentType, body []byte) (any, http.Header, error) {
var version eth2spec.DataVersion

Expand All @@ -1658,7 +1660,15 @@ func submitPayloadAttestationMessages(h Handler) handlerFunc {
return nil, nil, errors.Wrap(err, "unmarshal payload attestation messages")
}

err = h.SubmitPayloadAttestationMessages(ctx, msgs)
versioned := make([]*eth2spec.VersionedPayloadAttestationMessage, 0, len(msgs))
for _, msg := range msgs {
versioned = append(versioned, &eth2spec.VersionedPayloadAttestationMessage{
Version: version,
Gloas: msg,
})
}

err = s.SubmitPayloadAttestationMessages(ctx, &eth2api.SubmitPayloadAttestationMessagesOpts{Messages: versioned})
if err != nil {
return nil, nil, err
}
Expand Down
32 changes: 18 additions & 14 deletions core/validatorapi/router_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2288,8 +2288,8 @@ type testHandler struct {
SubmitSyncCommitteeMessagesFunc func(ctx context.Context, messages []*altair.SyncCommitteeMessage) error
SyncCommitteeDutiesFunc func(ctx context.Context, opts *eth2api.SyncCommitteeDutiesOpts) (*eth2api.Response[[]*eth2v1.SyncCommitteeDuty], error)
SyncCommitteeContributionFunc func(ctx context.Context, opts *eth2api.SyncCommitteeContributionOpts) (*eth2api.Response[*altair.SyncCommitteeContribution], error)
PayloadAttestationDataFunc func(ctx context.Context, slot uint64) (*gloas.PayloadAttestationData, error)
SubmitPayloadAttMsgsFunc func(ctx context.Context, messages []*gloas.PayloadAttestationMessage) error
PayloadAttestationDataFunc func(ctx context.Context, opts *eth2api.PayloadAttestationDataOpts) (*eth2api.Response[*eth2spec.VersionedPayloadAttestationData], error)
SubmitPayloadAttMsgsFunc func(ctx context.Context, opts *eth2api.SubmitPayloadAttestationMessagesOpts) error
ProxyFunc func(ctx context.Context, req *http.Request) (*http.Response, error)
AddressFunc func() string
HeadersFunc func() map[string]string
Expand All @@ -2299,12 +2299,12 @@ func (h testHandler) AttestationData(ctx context.Context, opts *eth2api.Attestat
return h.AttestationDataFunc(ctx, opts)
}

func (h testHandler) PayloadAttestationData(ctx context.Context, slot uint64) (*gloas.PayloadAttestationData, error) {
return h.PayloadAttestationDataFunc(ctx, slot)
func (h testHandler) PayloadAttestationData(ctx context.Context, opts *eth2api.PayloadAttestationDataOpts) (*eth2api.Response[*eth2spec.VersionedPayloadAttestationData], error) {
return h.PayloadAttestationDataFunc(ctx, opts)
}

func (h testHandler) SubmitPayloadAttestationMessages(ctx context.Context, messages []*gloas.PayloadAttestationMessage) error {
return h.SubmitPayloadAttMsgsFunc(ctx, messages)
func (h testHandler) SubmitPayloadAttestationMessages(ctx context.Context, opts *eth2api.SubmitPayloadAttestationMessagesOpts) error {
return h.SubmitPayloadAttMsgsFunc(ctx, opts)
}

func (h testHandler) AttesterDuties(ctx context.Context, opts *eth2api.AttesterDutiesOpts) (*eth2api.Response[[]*eth2v1.AttesterDuty], error) {
Expand Down Expand Up @@ -2572,10 +2572,13 @@ func TestPayloadAttestationRoutes(t *testing.T) {
expected.Slot = 42

handler := testHandler{
PayloadAttestationDataFunc: func(_ context.Context, slot uint64) (*gloas.PayloadAttestationData, error) {
require.Equal(t, uint64(42), slot)
PayloadAttestationDataFunc: func(_ context.Context, opts *eth2api.PayloadAttestationDataOpts) (*eth2api.Response[*eth2spec.VersionedPayloadAttestationData], error) {
require.Equal(t, eth2p0.Slot(42), opts.Slot)

return expected, nil
return wrapResponse(&eth2spec.VersionedPayloadAttestationData{
Version: eth2spec.DataVersionGloas,
Gloas: expected,
}), nil
},
}

Expand Down Expand Up @@ -2606,11 +2609,11 @@ func TestPayloadAttestationRoutes(t *testing.T) {
t.Run("submit_payload_attestations", func(t *testing.T) {
msg := testutil.RandomPayloadAttestationMessage()

var received []*gloas.PayloadAttestationMessage
var received []*eth2spec.VersionedPayloadAttestationMessage

handler := testHandler{
SubmitPayloadAttMsgsFunc: func(_ context.Context, messages []*gloas.PayloadAttestationMessage) error {
received = messages
SubmitPayloadAttMsgsFunc: func(_ context.Context, opts *eth2api.SubmitPayloadAttestationMessagesOpts) error {
received = opts.Messages

return nil
},
Expand All @@ -2632,15 +2635,16 @@ func TestPayloadAttestationRoutes(t *testing.T) {

require.Equal(t, http.StatusOK, resp.StatusCode)
require.Len(t, received, 1)
require.Equal(t, msg, received[0])
require.Equal(t, eth2spec.DataVersionGloas, received[0].Version)
require.Equal(t, msg, received[0].Gloas)
}

testRawRouter(t, handler, callback)
})

t.Run("submit_payload_attestations_bad_version_header", func(t *testing.T) {
handler := testHandler{
SubmitPayloadAttMsgsFunc: func(_ context.Context, _ []*gloas.PayloadAttestationMessage) error {
SubmitPayloadAttMsgsFunc: func(_ context.Context, _ *eth2api.SubmitPayloadAttestationMessagesOpts) error {
require.Fail(t, "handler must not be called")

return nil
Expand Down
27 changes: 20 additions & 7 deletions core/validatorapi/validatorapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -977,30 +977,43 @@ func (c Component) SubmitSyncCommitteeMessages(ctx context.Context, messages []*
return nil
}

// PayloadAttestationData returns the payload attestation data for the provided slot.
func (c Component) PayloadAttestationData(ctx context.Context, slot uint64) (*gloas.PayloadAttestationData, error) {
// PayloadAttestationData implements the eth2client.PayloadAttestationDataProvider for the router.
func (c Component) PayloadAttestationData(ctx context.Context, opts *eth2api.PayloadAttestationDataOpts) (*eth2api.Response[*eth2spec.VersionedPayloadAttestationData], error) {
var span trace.Span

duty := core.NewPayloadAttestationDuty(slot)
duty := core.NewPayloadAttestationDuty(uint64(opts.Slot))
ctx, span = core.StartDutyTrace(ctx, duty, "core/validatorapi.PayloadAttestationData")

defer span.End()

return c.awaitPayloadAttDataFunc(ctx, slot)
data, err := c.awaitPayloadAttDataFunc(ctx, uint64(opts.Slot))
if err != nil {
return nil, err
}

return wrapResponse(&eth2spec.VersionedPayloadAttestationData{
Version: eth2spec.DataVersionGloas,
Gloas: data,
}), nil
}

// SubmitPayloadAttestationMessages receives partially signed gloas.PayloadAttestationMessage.
// SubmitPayloadAttestationMessages implements the eth2client.PayloadAttestationMessagesSubmitter for the router.
// - It verifies the partial signature on each message.
// - It then calls all the subscribers for further steps on the partially signed messages.
func (c Component) SubmitPayloadAttestationMessages(ctx context.Context, messages []*gloas.PayloadAttestationMessage) error {
func (c Component) SubmitPayloadAttestationMessages(ctx context.Context, opts *eth2api.SubmitPayloadAttestationMessagesOpts) error {
vals, err := c.eth2Cl.ActiveValidators(ctx)
if err != nil {
return err
}

psigsBySlot := make(map[eth2p0.Slot]core.ParSignedDataSet)

for _, msg := range messages {
for _, versioned := range opts.Messages {
if versioned.Version != eth2spec.DataVersionGloas || versioned.Gloas == nil {
return errors.New("unsupported payload attestation message version")
}

msg := versioned.Gloas
if msg.Data == nil {
return errors.New("no payload attestation data")
}
Expand Down
9 changes: 6 additions & 3 deletions core/validatorapi/validatorapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2762,9 +2762,10 @@ func TestComponent_PayloadAttestationData(t *testing.T) {
return expected, nil
})

data, err := vapi.PayloadAttestationData(ctx, 42)
resp, err := vapi.PayloadAttestationData(ctx, &eth2api.PayloadAttestationDataOpts{Slot: 42})
require.NoError(t, err)
require.Equal(t, expected, data)
require.Equal(t, eth2spec.DataVersionGloas, resp.Data.Version)
require.Equal(t, expected, resp.Data.Gloas)
}

func TestComponent_SubmitPayloadAttestationMessages(t *testing.T) {
Expand Down Expand Up @@ -2800,6 +2801,8 @@ func TestComponent_SubmitPayloadAttestationMessages(t *testing.T) {
return nil
})

require.NoError(t, vapi.SubmitPayloadAttestationMessages(ctx, []*gloas.PayloadAttestationMessage{msg}))
require.NoError(t, vapi.SubmitPayloadAttestationMessages(ctx, &eth2api.SubmitPayloadAttestationMessagesOpts{
Messages: []*eth2spec.VersionedPayloadAttestationMessage{{Version: eth2spec.DataVersionGloas, Gloas: msg}},
}))
require.Equal(t, 1, count)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ require (
replace github.com/coinbase/kryptology => github.com/ObolNetwork/kryptology v0.1.0

// We're replacing go-eth2-client with a branch off our fork. The branch is kept up to date with the latest attestantio versions.
replace github.com/attestantio/go-eth2-client => github.com/ObolNetwork/go-eth2-client v0.29.0-obol.1-gloas //nolint
replace github.com/attestantio/go-eth2-client => github.com/ObolNetwork/go-eth2-client v0.29.0-obol.2-gloas //nolint

tool (
github.com/bufbuild/buf/cmd/buf
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE=
github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/ObolNetwork/go-eth2-client v0.29.0-obol.1-gloas h1:P33jtt5RE6+uROys1WOSOiwhJZ1lAQu2tUzS6v5XdKE=
github.com/ObolNetwork/go-eth2-client v0.29.0-obol.1-gloas/go.mod h1:yhVnKAzIsFhtawbq6k/rA/Dy4vsPpu2Z2cGdQVrIjd0=
github.com/ObolNetwork/go-eth2-client v0.29.0-obol.2-gloas h1:zWRrvhl/GHiTXTgeVk7ikTO4VMHEQy8kgHha8yr8R74=
github.com/ObolNetwork/go-eth2-client v0.29.0-obol.2-gloas/go.mod h1:yhVnKAzIsFhtawbq6k/rA/Dy4vsPpu2Z2cGdQVrIjd0=
github.com/ObolNetwork/kryptology v0.1.0 h1:AhoG4My70+xMhEJSpVaJay/t+T/vIUNHQYLjsDJHulI=
github.com/ObolNetwork/kryptology v0.1.0/go.mod h1:/Wl7Js2f676GyXZDTaojf/O+l0fxFPWudbyjdFhkpSA=
github.com/OffchainLabs/go-bitfield v0.0.0-20251031151322-f427d04d8506 h1:d/SJkN8/9Ca+1YmuDiUJxAiV4w/a9S8NcsG7GMQSrVI=
Expand Down
Loading