Skip to content

Commit

Permalink
refactor according to latest go-eth2-client changes
Browse files Browse the repository at this point in the history
  • Loading branch information
xenowits committed Oct 19, 2023
1 parent 2d06d96 commit 81aaaba
Show file tree
Hide file tree
Showing 34 changed files with 1,047 additions and 510 deletions.
4 changes: 3 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -809,10 +809,12 @@ func newETH2Client(ctx context.Context, conf Config, life *lifecycle.Manager,
}

// Check BN chain/network.
schedule, err := eth2Cl.ForkSchedule(ctx)
eth2Resp, err := eth2Cl.ForkSchedule(ctx)

Check warning on line 812 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L812

Added line #L812 was not covered by tests
if err != nil {
return nil, errors.Wrap(err, "fetch fork schedule")
}
schedule := eth2Resp.Data

Check warning on line 817 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L816-L817

Added lines #L816 - L817 were not covered by tests
var ok bool
for _, fork := range schedule {
if bytes.Equal(fork.CurrentVersion[:], forkVersion) {
Expand Down
11 changes: 6 additions & 5 deletions app/eth2wrap/eth2wrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"sync"
"time"

eth2api "github.com/attestantio/go-eth2-client/api"
eth2http "github.com/attestantio/go-eth2-client/http"
"github.com/attestantio/go-eth2-client/spec/bellatrix"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
Expand Down Expand Up @@ -329,12 +330,12 @@ func incError(endpoint string) {
// wrapError returns the error as a wrapped structured error.
func wrapError(ctx context.Context, err error, label string, fields ...z.Field) error {
// Decompose go-eth2-client http errors
if e2err := new(eth2http.Error); errors.As(err, e2err) {
if apiErr := new(eth2api.Error); errors.As(err, apiErr) {
err = errors.New("nok http response",
z.Int("status_code", e2err.StatusCode),
z.Str("endpoint", e2err.Endpoint),
z.Str("method", e2err.Method),
z.Str("data", string(e2err.Data)),
z.Int("status_code", apiErr.StatusCode),
z.Str("endpoint", apiErr.Endpoint),
z.Str("method", apiErr.Method),
z.Str("data", string(apiErr.Data)),

Check warning on line 338 in app/eth2wrap/eth2wrap.go

View check run for this annotation

Codecov / codecov/patch

app/eth2wrap/eth2wrap.go#L335-L338

Added lines #L335 - L338 were not covered by tests
)
}

Expand Down
300 changes: 162 additions & 138 deletions app/eth2wrap/eth2wrap_gen.go

Large diffs are not rendered by default.

14 changes: 1 addition & 13 deletions app/eth2wrap/eth2wrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func TestSyncState(t *testing.T) {

resp, err := eth2Cl.NodeSyncing(context.Background())
require.NoError(t, err)
require.False(t, resp.IsSyncing)
require.False(t, resp.Data.IsSyncing)
}

func TestErrors(t *testing.T) {
Expand Down Expand Up @@ -203,18 +203,6 @@ func TestErrors(t *testing.T) {
require.ErrorContains(t, err, "beacon api slots_per_epoch: context canceled")
})

t.Run("go-eth2-client http error", func(t *testing.T) {
bmock, err := beaconmock.New()
require.NoError(t, err)
eth2Cl, err := eth2wrap.NewMultiHTTP(time.Second, bmock.Address())
require.NoError(t, err)

_, err = eth2Cl.AggregateAttestation(ctx, 0, eth2p0.Root{})
log.Error(ctx, "See this error log for fields", err)
require.Error(t, err)
require.ErrorContains(t, err, "beacon api aggregate_attestation: nok http response")
})

t.Run("zero net op error", func(t *testing.T) {
bmock, err := beaconmock.New()
require.NoError(t, err)
Expand Down
2 changes: 2 additions & 0 deletions app/eth2wrap/genwrap/genwrap.go

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

11 changes: 6 additions & 5 deletions app/eth2wrap/success.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
package eth2wrap

import (
"github.com/attestantio/go-eth2-client/api"
apiv1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec/phase0"
)

// isSyncStateOk returns tue if the sync state is not syncing.
func isSyncStateOk(s *apiv1.SyncState) bool {
return !s.IsSyncing
// isSyncStateOk returns true if the sync state is not syncing.
func isSyncStateOk(resp *api.Response[*apiv1.SyncState]) bool {
return !resp.Data.IsSyncing
}

// isAggregateAttestationOk returns true if the aggregate attestation is not nil (which can happen if the subscription wasn't successful).
func isAggregateAttestationOk(att *phase0.Attestation) bool {
return att != nil
func isAggregateAttestationOk(resp *api.Response[*phase0.Attestation]) bool {
return resp.Data != nil

Check warning on line 18 in app/eth2wrap/success.go

View check run for this annotation

Codecov / codecov/patch

app/eth2wrap/success.go#L17-L18

Added lines #L17 - L18 were not covered by tests
}
62 changes: 48 additions & 14 deletions app/eth2wrap/synthproposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,14 @@ func (h *synthWrapper) getFeeRecipient(vIdx eth2p0.ValidatorIndex) bellatrix.Exe

// ProposerDuties returns upstream proposer duties for the provided validator indexes or
// upstream proposer duties and synthetic duties for all cluster validators if enabled.
func (h *synthWrapper) ProposerDuties(ctx context.Context, epoch eth2p0.Epoch, _ []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) {
func (h *synthWrapper) ProposerDuties(ctx context.Context, opts *api.ProposerDutiesOpts) (*api.Response[[]*eth2v1.ProposerDuty], error) {
// TODO(corver): Should we support fetching duties for other validators not in the cluster?
return h.synthProposerCache.Duties(ctx, h.Client, epoch)
duties, err := h.synthProposerCache.Duties(ctx, h.Client, opts.Epoch)
if err != nil {
return nil, err
}

Check warning on line 80 in app/eth2wrap/synthproposer.go

View check run for this annotation

Codecov / codecov/patch

app/eth2wrap/synthproposer.go#L79-L80

Added lines #L79 - L80 were not covered by tests

return &api.Response[[]*eth2v1.ProposerDuty]{Data: duties}, nil
}

func (h *synthWrapper) SubmitProposalPreparations(ctx context.Context, preparations []*eth2v1.ProposalPreparation) error {
Expand All @@ -84,32 +89,52 @@ func (h *synthWrapper) SubmitProposalPreparations(ctx context.Context, preparati
}

// BeaconBlockProposal returns an unsigned beacon block, possibly marked as synthetic.
func (h *synthWrapper) BeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randao eth2p0.BLSSignature, graffiti []byte) (*spec.VersionedBeaconBlock, error) {
vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, slot)
func (h *synthWrapper) BeaconBlockProposal(ctx context.Context, opts *api.BeaconBlockProposalOpts) (*api.Response[*spec.VersionedBeaconBlock], error) {
vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, opts.Slot)
if err != nil {
return nil, err
} else if !ok {
return h.Client.BeaconBlockProposal(ctx, slot, randao, graffiti)
resp, err := h.Client.BeaconBlockProposal(ctx, opts)
if err != nil {
return nil, errors.Wrap(err, "propose beacon block")
}

Check warning on line 100 in app/eth2wrap/synthproposer.go

View check run for this annotation

Codecov / codecov/patch

app/eth2wrap/synthproposer.go#L99-L100

Added lines #L99 - L100 were not covered by tests

return resp, nil
}

block, err := h.syntheticBlock(ctx, opts.Slot, vIdx)
if err != nil {
return nil, err

Check warning on line 107 in app/eth2wrap/synthproposer.go

View check run for this annotation

Codecov / codecov/patch

app/eth2wrap/synthproposer.go#L107

Added line #L107 was not covered by tests
}

return h.syntheticBlock(ctx, slot, vIdx)
return &api.Response[*spec.VersionedBeaconBlock]{Data: block}, nil
}

// BlindedBeaconBlockProposal returns an unsigned blinded beacon block, possibly marked as synthetic.
func (h *synthWrapper) BlindedBeaconBlockProposal(ctx context.Context, slot eth2p0.Slot, randao eth2p0.BLSSignature, graffiti []byte) (*api.VersionedBlindedBeaconBlock, error) {
vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, slot)
func (h *synthWrapper) BlindedBeaconBlockProposal(ctx context.Context, opts *api.BlindedBeaconBlockProposalOpts) (*api.Response[*api.VersionedBlindedBeaconBlock], error) {
vIdx, ok, err := h.synthProposerCache.SyntheticVIdx(ctx, h.Client, opts.Slot)
if err != nil {
return nil, err
} else if !ok {
return h.Client.BlindedBeaconBlockProposal(ctx, slot, randao, graffiti)
resp, err := h.Client.BlindedBeaconBlockProposal(ctx, opts)
if err != nil {
return nil, errors.Wrap(err, "propose blinded beacon block")
}

Check warning on line 122 in app/eth2wrap/synthproposer.go

View check run for this annotation

Codecov / codecov/patch

app/eth2wrap/synthproposer.go#L121-L122

Added lines #L121 - L122 were not covered by tests

return resp, nil
}

block, err := h.syntheticBlock(ctx, opts.Slot, vIdx)
if err != nil {
return nil, err

Check warning on line 129 in app/eth2wrap/synthproposer.go

View check run for this annotation

Codecov / codecov/patch

app/eth2wrap/synthproposer.go#L129

Added line #L129 was not covered by tests
}

block, err := h.syntheticBlock(ctx, slot, vIdx)
syncBlindedBlock, err := blindedBlock(block)
if err != nil {
return nil, err
}

return blindedBlock(block)
return &api.Response[*api.VersionedBlindedBeaconBlock]{Data: syncBlindedBlock}, nil
}

// syntheticBlock returns a synthetic beacon block to propose.
Expand All @@ -118,14 +143,17 @@ func (h *synthWrapper) syntheticBlock(ctx context.Context, slot eth2p0.Slot, vId

// Work our way back from previous slot to find a block to base the synthetic block on.
for prev := slot - 1; prev > 0; prev-- {
signed, err := h.Client.SignedBeaconBlock(ctx, fmt.Sprint(prev))
opts := &api.SignedBeaconBlockOpts{
Block: fmt.Sprint(prev),
}
signed, err := h.Client.SignedBeaconBlock(ctx, opts)
if err != nil {
return nil, err
} else if signed == nil { // go-eth2-client returns nil if block is not found.
continue
}

signedBlock = signed
signedBlock = signed.Data

break
}
Expand Down Expand Up @@ -279,11 +307,17 @@ func (c *synthProposerCache) Duties(ctx context.Context, eth2Cl synthProposerEth
}

// Get actual duties for all validators for the epoch.
duties, err = eth2Cl.ProposerDuties(ctx, epoch, vals.Indices())
opts := &api.ProposerDutiesOpts{
Epoch: epoch,
Indices: vals.Indices(),
}
resp, err := eth2Cl.ProposerDuties(ctx, opts)
if err != nil {
return nil, err
}

duties = resp.Data

// Get slotsPerEpoch and the starting slot of the epoch.
slotsPerEpoch, err := eth2Cl.SlotsPerEpoch(ctx)
if err != nil {
Expand Down
41 changes: 33 additions & 8 deletions app/eth2wrap/synthproposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package eth2wrap_test

import (
"context"
"math/rand"
"testing"

eth2api "github.com/attestantio/go-eth2-client/api"
Expand Down Expand Up @@ -59,11 +58,13 @@ func TestSynthProposer(t *testing.T) {
}
signedBeaconBlock := bmock.SignedBeaconBlock
bmock.SignedBeaconBlockFunc = func(ctx context.Context, blockID string) (*spec.VersionedSignedBeaconBlock, error) {
if rand.Float32() < 0.3 { // Fail to find 2/3 of blocks.
return nil, nil //nolint:nilnil // go-eth2-client returns nilnil if block not found.
opts := &eth2api.SignedBeaconBlockOpts{Block: blockID}
resp, err := signedBeaconBlock(ctx, opts)
if err != nil {
return nil, err
}

return signedBeaconBlock(ctx, blockID)
return resp.Data, nil
}

eth2Cl := eth2wrap.WithSyntheticDuties(bmock)
Expand All @@ -78,21 +79,37 @@ func TestSynthProposer(t *testing.T) {
require.NoError(t, eth2Cl.SubmitProposalPreparations(ctx, preps))

// Get synthetic duties
duties, err := eth2Cl.ProposerDuties(ctx, epoch, nil)
opts := &eth2api.ProposerDutiesOpts{
Epoch: epoch,
Indices: nil,
}
resp1, err := eth2Cl.ProposerDuties(ctx, opts)
require.NoError(t, err)
duties := resp1.Data
require.Len(t, duties, len(set))
require.Equal(t, 1, activeVals)

// Get synthetic duties again
duties2, err := eth2Cl.ProposerDuties(ctx, epoch, nil)
resp2, err := eth2Cl.ProposerDuties(ctx, opts)
require.NoError(t, err)
duties2 := resp2.Data
require.Equal(t, duties, duties2) // Identical
require.Equal(t, 1, activeVals) // Cached

// Submit blocks
for _, duty := range duties {
block, err := eth2Cl.BeaconBlockProposal(ctx, duty.Slot, testutil.RandomEth2Signature(), []byte("test"))
var graff [32]byte
copy(graff[:], "test")
opts1 := &eth2api.BeaconBlockProposalOpts{
Slot: duty.Slot,
RandaoReveal: testutil.RandomEth2Signature(),
Graffiti: graff,
}

resp, err := eth2Cl.BeaconBlockProposal(ctx, opts1)
require.NoError(t, err)
block := resp.Data

if duty.Slot == realBlockSlot {
require.NotContains(t, string(block.Capella.Body.Graffiti[:]), "DO NOT SUBMIT")
require.NotEqual(t, feeRecipient, block.Capella.Body.ExecutionPayload.FeeRecipient)
Expand All @@ -110,8 +127,16 @@ func TestSynthProposer(t *testing.T) {

// Submit blinded blocks
for _, duty := range duties {
block, err := eth2Cl.BlindedBeaconBlockProposal(ctx, duty.Slot, testutil.RandomEth2Signature(), []byte("test"))
var graff [32]byte
copy(graff[:], "test")
opts := &eth2api.BlindedBeaconBlockProposalOpts{
Slot: duty.Slot,
RandaoReveal: testutil.RandomEth2Signature(),
Graffiti: graff,
}
resp, err := eth2Cl.BlindedBeaconBlockProposal(ctx, opts)
require.NoError(t, err)
block := resp.Data
if duty.Slot == realBlockSlot {
require.NotContains(t, string(block.Capella.Body.Graffiti[:]), "DO NOT SUBMIT")
require.NotEqual(t, feeRecipient, block.Capella.Body.ExecutionPayloadHeader.FeeRecipient)
Expand Down
8 changes: 7 additions & 1 deletion app/eth2wrap/valcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"context"
"sync"

eth2api "github.com/attestantio/go-eth2-client/api"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"

"github.com/obolnetwork/charon/app/errors"
Expand Down Expand Up @@ -88,10 +89,15 @@ func (c *ValidatorCache) Get(ctx context.Context) (ActiveValidators, error) {
return c.active, nil
}

vals, err := c.eth2Cl.ValidatorsByPubKey(ctx, "head", c.pubkeys)
opts := &eth2api.ValidatorsOpts{
State: "head",
PubKeys: c.pubkeys,
}
eth2Resp, err := c.eth2Cl.Validators(ctx, opts)
if err != nil {
return nil, err
}
vals := eth2Resp.Data

resp := make(ActiveValidators)
for _, val := range vals {
Expand Down
7 changes: 4 additions & 3 deletions app/eth2wrap/valcache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math/rand"
"testing"

eth2api "github.com/attestantio/go-eth2-client/api"
eth2v1 "github.com/attestantio/go-eth2-client/api/v1"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -42,10 +43,10 @@ func TestValidatorCache(t *testing.T) {

// Configure it to return the set of validators if queried.
var queried int
eth2Cl.ValidatorsByPubKeyFunc = func(ctx context.Context, stateID string, keys []eth2p0.BLSPubKey) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) {
eth2Cl.ValidatorsFunc = func(ctx context.Context, opts *eth2api.ValidatorsOpts) (map[eth2p0.ValidatorIndex]*eth2v1.Validator, error) {
queried++
require.Equal(t, "head", stateID)
require.Equal(t, pubkeys, keys)
require.Equal(t, "head", opts.State)
require.Equal(t, pubkeys, opts.PubKeys)

return set, nil
}
Expand Down
7 changes: 4 additions & 3 deletions app/monitoringapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,24 +205,25 @@ func startReadyChecker(ctx context.Context, tcpNode host.Host, eth2Cl eth2wrap.C
// beaconNodeSyncing returns true if the beacon node is still syncing. It also returns the sync distance, ie, the distance
// between the node's highest synced slot and the head slot.
func beaconNodeSyncing(ctx context.Context, eth2Cl eth2client.NodeSyncingProvider) (bool, eth2p0.Slot, error) {
state, err := eth2Cl.NodeSyncing(ctx)
eth2Resp, err := eth2Cl.NodeSyncing(ctx)
if err != nil {
return false, 0, err
}

return state.IsSyncing, state.SyncDistance, nil
return eth2Resp.Data.IsSyncing, eth2Resp.Data.SyncDistance, nil
}

// beaconNodeVersionMetric sets the beacon node version gauge.
func beaconNodeVersionMetric(ctx context.Context, eth2Cl eth2wrap.Client, clock clockwork.Clock) {
nodeVersionTicker := clock.NewTicker(10 * time.Minute)

setNodeVersion := func() {
version, err := eth2Cl.NodeVersion(ctx)
eth2Resp, err := eth2Cl.NodeVersion(ctx)

Check warning on line 221 in app/monitoringapi.go

View check run for this annotation

Codecov / codecov/patch

app/monitoringapi.go#L221

Added line #L221 was not covered by tests
if err != nil {
log.Error(ctx, "Failed to get beacon node version", err)
return
}
version := eth2Resp.Data

Check warning on line 226 in app/monitoringapi.go

View check run for this annotation

Codecov / codecov/patch

app/monitoringapi.go#L226

Added line #L226 was not covered by tests

beaconNodeVersionGauge.Reset()
beaconNodeVersionGauge.WithLabelValues(version).Set(1)
Expand Down
Loading

0 comments on commit 81aaaba

Please sign in to comment.