From 51c286ef1a7d1eaa2d808b84daa270b232c4715b Mon Sep 17 00:00:00 2001 From: Andrei Smirnov Date: Tue, 5 Mar 2024 14:56:15 +0300 Subject: [PATCH] *: revert new v3 endpoint work --- app/eth2wrap/eth2wrap_gen.go | 31 --- app/eth2wrap/genwrap/genwrap.go | 1 - core/dutydb/memory.go | 133 +----------- core/dutydb/memory_internal_test.go | 5 - core/dutydb/memory_test.go | 136 ------------ core/fetcher/fetcher.go | 99 +++------ core/fetcher/fetcher_test.go | 51 ----- core/signeddata.go | 200 ------------------ core/signeddata_test.go | 28 --- ...ation_VersionedBlindedProposal.json.golden | 3 +- ...VersionedSignedBlindedProposal.json.golden | 3 +- core/types.go | 18 +- core/types_test.go | 10 +- core/unsigneddata.go | 69 ------ core/unsigneddata_test.go | 29 --- go.mod | 3 - go.sum | 4 +- testutil/beaconmock/beaconmock.go | 10 - testutil/beaconmock/beaconmock_fuzz.go | 7 - testutil/beaconmock/options.go | 13 -- testutil/validatormock/component.go | 4 - testutil/validatormock/propose.go | 159 +++++++------- testutil/validatormock/propose_test.go | 48 ----- 23 files changed, 119 insertions(+), 945 deletions(-) diff --git a/app/eth2wrap/eth2wrap_gen.go b/app/eth2wrap/eth2wrap_gen.go index 50f12f384..c679fed0d 100644 --- a/app/eth2wrap/eth2wrap_gen.go +++ b/app/eth2wrap/eth2wrap_gen.go @@ -59,7 +59,6 @@ type Client interface { eth2client.SyncCommitteeDutiesProvider eth2client.SyncCommitteeMessagesSubmitter eth2client.SyncCommitteeSubscriptionsSubmitter - eth2client.UniversalProposalProvider eth2client.ValidatorRegistrationsSubmitter eth2client.ValidatorsProvider eth2client.VoluntaryExitSubmitter @@ -370,26 +369,6 @@ func (m multi) Proposal(ctx context.Context, opts *api.ProposalOpts) (*api.Respo return res0, err } -// Proposal fetches a universal proposal for signing. -func (m multi) UniversalProposal(ctx context.Context, opts *api.UniversalProposalOpts) (*api.Response[*api.VersionedUniversalProposal], error) { - const label = "universal_proposal" - defer latency(label)() - - res0, err := provide(ctx, m.clients, - func(ctx context.Context, cl Client) (*api.Response[*api.VersionedUniversalProposal], error) { - return cl.UniversalProposal(ctx, opts) - }, - nil, m.selector, - ) - - if err != nil { - incError(label) - err = wrapError(ctx, err, label) - } - - return res0, err -} - // BeaconBlockRoot fetches a block's root given a set of options. // Note this endpoint is cached in go-eth2-client. func (m multi) BeaconBlockRoot(ctx context.Context, opts *api.BeaconBlockRootOpts) (*api.Response[*phase0.Root], error) { @@ -929,16 +908,6 @@ func (l *lazy) Proposal(ctx context.Context, opts *api.ProposalOpts) (res0 *api. return cl.Proposal(ctx, opts) } -// Proposal fetches a universal proposal for signing. -func (l *lazy) UniversalProposal(ctx context.Context, opts *api.UniversalProposalOpts) (res0 *api.Response[*api.VersionedUniversalProposal], err error) { - cl, err := l.getOrCreateClient(ctx) - if err != nil { - return res0, err - } - - return cl.UniversalProposal(ctx, opts) -} - // BeaconBlockRoot fetches a block's root given a set of options. func (l *lazy) BeaconBlockRoot(ctx context.Context, opts *api.BeaconBlockRootOpts) (res0 *api.Response[*phase0.Root], err error) { cl, err := l.getOrCreateClient(ctx) diff --git a/app/eth2wrap/genwrap/genwrap.go b/app/eth2wrap/genwrap/genwrap.go index 504066f5f..45981cad3 100644 --- a/app/eth2wrap/genwrap/genwrap.go +++ b/app/eth2wrap/genwrap/genwrap.go @@ -125,7 +125,6 @@ type Client interface { "SyncCommitteeContributionsSubmitter": true, "SyncCommitteeMessagesSubmitter": true, "SyncCommitteeSubscriptionsSubmitter": true, - "UniversalProposalProvider": true, "ValidatorsProvider": true, "ValidatorRegistrationsSubmitter": true, "VoluntaryExitSubmitter": true, diff --git a/core/dutydb/memory.go b/core/dutydb/memory.go index 39f22c05d..eff6d0bcb 100644 --- a/core/dutydb/memory.go +++ b/core/dutydb/memory.go @@ -18,18 +18,17 @@ import ( // NewMemDB returns a new in-memory dutyDB instance. func NewMemDB(deadliner core.Deadliner) *MemDB { return &MemDB{ - attDuties: make(map[attKey]*eth2p0.AttestationData), - attPubKeys: make(map[pkKey]core.PubKey), - attKeysBySlot: make(map[uint64][]pkKey), - builderProDuties: make(map[uint64]*eth2api.VersionedBlindedProposal), - proDuties: make(map[uint64]*eth2api.VersionedProposal), - universalProDuties: make(map[uint64]*eth2api.VersionedUniversalProposal), - aggDuties: make(map[aggKey]core.AggregatedAttestation), - aggKeysBySlot: make(map[uint64][]aggKey), - contribDuties: make(map[contribKey]*altair.SyncCommitteeContribution), - contribKeysBySlot: make(map[uint64][]contribKey), - shutdown: make(chan struct{}), - deadliner: deadliner, + attDuties: make(map[attKey]*eth2p0.AttestationData), + attPubKeys: make(map[pkKey]core.PubKey), + attKeysBySlot: make(map[uint64][]pkKey), + builderProDuties: make(map[uint64]*eth2api.VersionedBlindedProposal), + proDuties: make(map[uint64]*eth2api.VersionedProposal), + aggDuties: make(map[aggKey]core.AggregatedAttestation), + aggKeysBySlot: make(map[uint64][]aggKey), + contribDuties: make(map[contribKey]*altair.SyncCommitteeContribution), + contribKeysBySlot: make(map[uint64][]contribKey), + shutdown: make(chan struct{}), + deadliner: deadliner, } } @@ -52,10 +51,6 @@ type MemDB struct { proDuties map[uint64]*eth2api.VersionedProposal proQueries []proQuery - // DutyUniversalProposer - universalProDuties map[uint64]*eth2api.VersionedUniversalProposal - universalProQueries []universalProQuery - // DutyAggregator aggDuties map[aggKey]core.AggregatedAttestation aggKeysBySlot map[uint64][]aggKey @@ -110,18 +105,6 @@ func (db *MemDB) Store(_ context.Context, duty core.Duty, unsignedSet core.Unsig } } db.resolveBuilderProQueriesUnsafe() - case core.DutyUniversalProposer: - // Sanity check max one universal proposer per slot - if len(unsignedSet) > 1 { - return errors.New("unexpected universal proposer data set length", z.Int("n", len(unsignedSet))) - } - for _, unsignedData := range unsignedSet { - err := db.storeUniversalProposalUnsafe(unsignedData) - if err != nil { - return err - } - } - db.resolveUniversalProQueriesUnsafe() case core.DutyAttester: for pubkey, unsignedData := range unsignedSet { err := db.storeAttestationUnsafe(pubkey, unsignedData) @@ -221,31 +204,6 @@ func (db *MemDB) AwaitBlindedProposal(ctx context.Context, slot uint64) (*eth2ap } } -// AwaitUniversalProposal implements core.DutyDB, see its godoc. -func (db *MemDB) AwaitUniversalProposal(ctx context.Context, slot uint64) (*eth2api.VersionedUniversalProposal, error) { - cancel := make(chan struct{}) - defer close(cancel) - response := make(chan *eth2api.VersionedUniversalProposal, 1) - - db.mu.Lock() - db.universalProQueries = append(db.universalProQueries, universalProQuery{ - Key: slot, - Response: response, - Cancel: cancel, - }) - db.resolveUniversalProQueriesUnsafe() - db.mu.Unlock() - - select { - case <-db.shutdown: - return nil, errors.New("dutydb shutdown") - case <-ctx.Done(): - return nil, ctx.Err() - case block := <-response: - return block, nil - } -} - // AwaitAttestation implements core.DutyDB, see its godoc. func (db *MemDB) AwaitAttestation(ctx context.Context, slot uint64, commIdx uint64) (*eth2p0.AttestationData, error) { cancel := make(chan struct{}) @@ -531,45 +489,6 @@ func (db *MemDB) storeProposalUnsafe(unsignedData core.UnsignedData) error { return nil } -// storeUniversalProposalUnsafe stores the unsigned UniversalProposal. -// It is unsafe since it assumes the lock is held. -func (db *MemDB) storeUniversalProposalUnsafe(unsignedData core.UnsignedData) error { - cloned, err := unsignedData.Clone() // Clone before storing. - if err != nil { - return err - } - - proposal, ok := cloned.(core.VersionedUniversalProposal) - if !ok { - return errors.New("invalid versioned universal proposal") - } - - slot, err := proposal.Slot() - if err != nil { - return err - } - - if existing, ok := db.universalProDuties[uint64(slot)]; ok { - existingRoot, err := existing.Root() - if err != nil { - return errors.Wrap(err, "universal proposal root") - } - - providedRoot, err := proposal.Root() - if err != nil { - return errors.Wrap(err, "universal proposal root") - } - - if existingRoot != providedRoot { - return errors.New("clashing blocks") - } - } else { - db.universalProDuties[uint64(slot)] = &proposal.VersionedUniversalProposal - } - - return nil -} - // storeBlindedBeaconBlockUnsafe stores the unsigned BlindedBeaconBlock. It is unsafe since it assumes the lock is held. func (db *MemDB) storeBlindedBeaconBlockUnsafe(unsignedData core.UnsignedData) error { cloned, err := unsignedData.Clone() // Clone before storing. @@ -650,27 +569,6 @@ func (db *MemDB) resolveProQueriesUnsafe() { db.proQueries = unresolved } -// resolveUniversalProQueriesUnsafe resolve any universalProQuery to a result if found. -// It is unsafe since it assume that the lock is held. -func (db *MemDB) resolveUniversalProQueriesUnsafe() { - var unresolved []universalProQuery - for _, query := range db.universalProQueries { - if cancelled(query.Cancel) { - continue // Drop cancelled queries. - } - - value, ok := db.universalProDuties[query.Key] - if !ok { - unresolved = append(unresolved, query) - continue - } - - query.Response <- value - } - - db.universalProQueries = unresolved -} - // resolveAggQueriesUnsafe resolve any aggQuery to a result if found. // It is unsafe since it assume that the lock is held. func (db *MemDB) resolveAggQueriesUnsafe() { @@ -741,8 +639,6 @@ func (db *MemDB) deleteDutyUnsafe(duty core.Duty) error { delete(db.proDuties, duty.Slot) case core.DutyBuilderProposer: delete(db.builderProDuties, duty.Slot) - case core.DutyUniversalProposer: - delete(db.universalProDuties, duty.Slot) case core.DutyAttester: for _, key := range db.attKeysBySlot[duty.Slot] { delete(db.attPubKeys, key) @@ -806,13 +702,6 @@ type proQuery struct { Cancel <-chan struct{} } -// universalProQuery is a waiting universalProQuery with a response channel. -type universalProQuery struct { - Key uint64 - Response chan<- *eth2api.VersionedUniversalProposal - Cancel <-chan struct{} -} - // aggQuery is a waiting aggQuery with a response channel. type aggQuery struct { Key aggKey diff --git a/core/dutydb/memory_internal_test.go b/core/dutydb/memory_internal_test.go index d967441a7..9101cec6a 100644 --- a/core/dutydb/memory_internal_test.go +++ b/core/dutydb/memory_internal_test.go @@ -33,9 +33,6 @@ func TestCancelledQueries(t *testing.T) { _, err = db.AwaitBlindedProposal(ctx, slot) require.ErrorContains(t, err, "shutdown") - _, err = db.AwaitUniversalProposal(ctx, slot) - require.ErrorContains(t, err, "shutdown") - _, err = db.AwaitSyncContribution(ctx, slot, 0, eth2p0.Root{}) require.ErrorContains(t, err, "shutdown") @@ -45,7 +42,6 @@ func TestCancelledQueries(t *testing.T) { require.NotEmpty(t, db.proQueries) require.NotEmpty(t, db.aggQueries) require.NotEmpty(t, db.builderProQueries) - require.NotEmpty(t, db.universalProQueries) // Resolve queries db.resolveAggQueriesUnsafe() @@ -53,7 +49,6 @@ func TestCancelledQueries(t *testing.T) { db.resolveContribQueriesUnsafe() db.resolveProQueriesUnsafe() db.resolveBuilderProQueriesUnsafe() - db.resolveUniversalProQueriesUnsafe() // Ensure all queries are gone. require.Empty(t, db.contribQueries) diff --git a/core/dutydb/memory_test.go b/core/dutydb/memory_test.go index 25aaf4d7e..04866b7cd 100644 --- a/core/dutydb/memory_test.go +++ b/core/dutydb/memory_test.go @@ -176,59 +176,6 @@ func TestMemDBProposer(t *testing.T) { } } -func TestMemDBUniversalProposer(t *testing.T) { - ctx := context.Background() - db := dutydb.NewMemDB(new(testDeadliner)) - - const queries = 3 - slots := [queries]uint64{123, 456, 789} - - type response struct { - block *eth2api.VersionedUniversalProposal - } - var awaitResponse [queries]chan response - for i := 0; i < queries; i++ { - awaitResponse[i] = make(chan response) - go func(slot int) { - block, err := db.AwaitUniversalProposal(ctx, slots[slot]) - require.NoError(t, err) - awaitResponse[slot] <- response{block: block} - }(i) - } - - proposals := make([]*eth2api.VersionedUniversalProposal, queries) - pubkeysByIdx := make(map[eth2p0.ValidatorIndex]core.PubKey) - for i := 0; i < queries; i++ { - proposals[i] = ð2api.VersionedUniversalProposal{ - Proposal: ð2api.VersionedProposal{ - Version: eth2spec.DataVersionBellatrix, - Bellatrix: testutil.RandomBellatrixBeaconBlock(), - }, - } - proposals[i].Proposal.Bellatrix.Slot = eth2p0.Slot(slots[i]) - proposals[i].Proposal.Bellatrix.ProposerIndex = eth2p0.ValidatorIndex(i) - pubkeysByIdx[eth2p0.ValidatorIndex(i)] = testutil.RandomCorePubKey(t) - } - - // Store the Blocks - for i := 0; i < queries; i++ { - unsigned, err := core.NewVersionedUniversalProposal(proposals[i]) - require.NoError(t, err) - - duty := core.Duty{Slot: slots[i], Type: core.DutyUniversalProposer} - err = db.Store(ctx, duty, core.UnsignedDataSet{ - pubkeysByIdx[eth2p0.ValidatorIndex(i)]: unsigned, - }) - require.NoError(t, err) - } - - // Get and assert the proQuery responses - for i := 0; i < queries; i++ { - actualData := <-awaitResponse[i] - require.Equal(t, proposals[i], actualData.block) - } -} - func TestMemDBAggregator(t *testing.T) { ctx := context.Background() db := dutydb.NewMemDB(new(testDeadliner)) @@ -386,47 +333,6 @@ func TestMemDBClashingBlocks(t *testing.T) { require.ErrorContains(t, err, "clashing blocks") } -func TestMemDBClashingUniversalBlocks(t *testing.T) { - ctx := context.Background() - db := dutydb.NewMemDB(new(testDeadliner)) - - const slot = 123 - block1 := ð2api.VersionedUniversalProposal{ - Proposal: ð2api.VersionedProposal{ - Version: eth2spec.DataVersionBellatrix, - Bellatrix: testutil.RandomBellatrixBeaconBlock(), - }, - } - block1.Proposal.Bellatrix.Slot = eth2p0.Slot(slot) - block2 := ð2api.VersionedUniversalProposal{ - Proposal: ð2api.VersionedProposal{ - Version: eth2spec.DataVersionBellatrix, - Bellatrix: testutil.RandomBellatrixBeaconBlock(), - }, - } - block2.Proposal.Bellatrix.Slot = eth2p0.Slot(slot) - pubkey := testutil.RandomCorePubKey(t) - - // Encode the Blocks - unsigned1, err := core.NewVersionedUniversalProposal(block1) - require.NoError(t, err) - - unsigned2, err := core.NewVersionedUniversalProposal(block2) - require.NoError(t, err) - - // Store the Blocks - duty := core.Duty{Slot: slot, Type: core.DutyUniversalProposer} - err = db.Store(ctx, duty, core.UnsignedDataSet{ - pubkey: unsigned1, - }) - require.NoError(t, err) - - err = db.Store(ctx, duty, core.UnsignedDataSet{ - pubkey: unsigned2, - }) - require.ErrorContains(t, err, "clashing blocks") -} - func TestMemDBClashProposer(t *testing.T) { ctx := context.Background() db := dutydb.NewMemDB(new(testDeadliner)) @@ -467,48 +373,6 @@ func TestMemDBClashProposer(t *testing.T) { require.ErrorContains(t, err, "clashing blocks") } -func TestMemDBClashUniversalProposer(t *testing.T) { - ctx := context.Background() - db := dutydb.NewMemDB(new(testDeadliner)) - - const slot = 123 - - block := ð2api.VersionedUniversalProposal{ - Proposal: ð2api.VersionedProposal{ - Version: eth2spec.DataVersionBellatrix, - Bellatrix: testutil.RandomBellatrixBeaconBlock(), - }, - } - block.Proposal.Bellatrix.Slot = eth2p0.Slot(slot) - pubkey := testutil.RandomCorePubKey(t) - - // Encode the block - unsigned, err := core.NewVersionedUniversalProposal(block) - require.NoError(t, err) - - // Store the Blocks - duty := core.Duty{Slot: slot, Type: core.DutyUniversalProposer} - err = db.Store(ctx, duty, core.UnsignedDataSet{ - pubkey: unsigned, - }) - require.NoError(t, err) - - // Store same block from same validator to test idempotent inserts - err = db.Store(ctx, duty, core.UnsignedDataSet{ - pubkey: unsigned, - }) - require.NoError(t, err) - - // Store a different block for the same slot - block.Proposal.Bellatrix.ProposerIndex++ - unsignedB, err := core.NewVersionedUniversalProposal(block) - require.NoError(t, err) - err = db.Store(ctx, duty, core.UnsignedDataSet{ - pubkey: unsignedB, - }) - require.ErrorContains(t, err, "clashing blocks") -} - func TestMemDBBuilderProposer(t *testing.T) { ctx := context.Background() db := dutydb.NewMemDB(new(testDeadliner)) diff --git a/core/fetcher/fetcher.go b/core/fetcher/fetcher.go index 3d223f966..64a97c944 100644 --- a/core/fetcher/fetcher.go +++ b/core/fetcher/fetcher.go @@ -51,26 +51,21 @@ func (f *Fetcher) Fetch(ctx context.Context, duty core.Duty, defSet core.DutyDef ) switch duty.Type { - case core.DutyAttester: - unsignedSet, err = f.fetchAttesterData(ctx, duty.Slot, defSet) - if err != nil { - return errors.Wrap(err, "fetch attester data") - } case core.DutyProposer: unsignedSet, err = f.fetchProposerData(ctx, duty.Slot, defSet) if err != nil { return errors.Wrap(err, "fetch proposer data") } + case core.DutyAttester: + unsignedSet, err = f.fetchAttesterData(ctx, duty.Slot, defSet) + if err != nil { + return errors.Wrap(err, "fetch attester data") + } case core.DutyBuilderProposer: unsignedSet, err = f.fetchBuilderProposerData(ctx, duty.Slot, defSet) if err != nil { return errors.Wrap(err, "fetch builder proposer data") } - case core.DutyUniversalProposer: - unsignedSet, err = f.fetchUniversalProposerData(ctx, duty.Slot, defSet) - if err != nil { - return errors.Wrap(err, "fetch universal proposer data") - } case core.DutyAggregator: unsignedSet, err = f.fetchAggregatorData(ctx, duty.Slot, defSet) if err != nil { @@ -239,35 +234,23 @@ func (f *Fetcher) fetchAggregatorData(ctx context.Context, slot uint64, defSet c return resp, nil } -func (f *Fetcher) getProposalOpts(ctx context.Context, slot uint64, pubkey core.PubKey) (eth2p0.BLSSignature, [32]byte, error) { - // Fetch previously aggregated randao reveal from AggSigDB - dutyRandao := core.Duty{ - Slot: slot, - Type: core.DutyRandao, - } - randaoData, err := f.aggSigDBFunc(ctx, dutyRandao, pubkey) - if err != nil { - return eth2p0.BLSSignature{}, [32]byte{}, err - } - - randao := randaoData.Signature().ToETH2() - - // TODO(dhruv): replace hardcoded graffiti with the one from cluster-lock.json - var graffiti [32]byte - commitSHA, _ := version.GitCommit() - copy(graffiti[:], fmt.Sprintf("charon/%v-%s", version.Version, commitSHA)) - - return randao, graffiti, nil -} - func (f *Fetcher) fetchProposerData(ctx context.Context, slot uint64, defSet core.DutyDefinitionSet) (core.UnsignedDataSet, error) { resp := make(core.UnsignedDataSet) for pubkey := range defSet { - randao, graffiti, err := f.getProposalOpts(ctx, slot, pubkey) + // Fetch previously aggregated randao reveal from AggSigDB + dutyRandao := core.NewRandaoDuty(slot) + randaoData, err := f.aggSigDBFunc(ctx, dutyRandao, pubkey) if err != nil { return nil, err } + randao := randaoData.Signature().ToETH2() + + // TODO(dhruv): replace hardcoded graffiti with the one from cluster-lock.json + var graffiti [32]byte + commitSHA, _ := version.GitCommit() + copy(graffiti[:], fmt.Sprintf("charon/%v-%s", version.Version, commitSHA)) + opts := ð2api.ProposalOpts{ Slot: eth2p0.Slot(slot), RandaoReveal: randao, @@ -296,11 +279,23 @@ func (f *Fetcher) fetchProposerData(ctx context.Context, slot uint64, defSet cor func (f *Fetcher) fetchBuilderProposerData(ctx context.Context, slot uint64, defSet core.DutyDefinitionSet) (core.UnsignedDataSet, error) { resp := make(core.UnsignedDataSet) for pubkey := range defSet { - randao, graffiti, err := f.getProposalOpts(ctx, slot, pubkey) + // Fetch previously aggregated randao reveal from AggSigDB + dutyRandao := core.Duty{ + Slot: slot, + Type: core.DutyRandao, + } + randaoData, err := f.aggSigDBFunc(ctx, dutyRandao, pubkey) if err != nil { return nil, err } + randao := randaoData.Signature().ToETH2() + + // TODO(dhruv): replace hardcoded graffiti with the one from cluster-lock.json + var graffiti [32]byte + commitSHA, _ := version.GitCommit() + copy(graffiti[:], fmt.Sprintf("charon/%v-%s", version.Version, commitSHA)) + opts := ð2api.BlindedProposalOpts{ Slot: eth2p0.Slot(slot), RandaoReveal: randao, @@ -325,44 +320,6 @@ func (f *Fetcher) fetchBuilderProposerData(ctx context.Context, slot uint64, def return resp, nil } -func (f *Fetcher) fetchUniversalProposerData(ctx context.Context, slot uint64, defSet core.DutyDefinitionSet) (core.UnsignedDataSet, error) { - resp := make(core.UnsignedDataSet) - for pubkey := range defSet { - randao, graffiti, err := f.getProposalOpts(ctx, slot, pubkey) - if err != nil { - return nil, err - } - - opts := ð2api.UniversalProposalOpts{ - Slot: eth2p0.Slot(slot), - RandaoReveal: randao, - Graffiti: graffiti, - BuilderBoostFactor: "", // TODO: how to populate this? - } - eth2Resp, err := f.eth2Cl.UniversalProposal(ctx, opts) - if err != nil { - return nil, err - } - proposal := eth2Resp.Data - - // Ensure fee recipient is correctly populated in proposal. - if proposal.Proposal != nil { - verifyFeeRecipient(ctx, proposal.Proposal, f.feeRecipientFunc(pubkey)) - } else if proposal.BlindedProposal != nil { - verifyFeeRecipientBlinded(ctx, proposal.BlindedProposal, f.feeRecipientFunc(pubkey)) - } - - coreProposal, err := core.NewVersionedUniversalProposal(proposal) - if err != nil { - return nil, errors.Wrap(err, "new universal proposal") - } - - resp[pubkey] = coreProposal - } - - return resp, nil -} - // fetchContributionData fetches the sync committee contribution data. func (f *Fetcher) fetchContributionData(ctx context.Context, slot uint64, defSet core.DutyDefinitionSet) (core.UnsignedDataSet, error) { resp := make(core.UnsignedDataSet) diff --git a/core/fetcher/fetcher_test.go b/core/fetcher/fetcher_test.go index b18321cbc..f3645e928 100644 --- a/core/fetcher/fetcher_test.go +++ b/core/fetcher/fetcher_test.go @@ -345,42 +345,6 @@ func TestFetchBlocks(t *testing.T) { err = fetch.Fetch(ctx, duty, defSet) require.NoError(t, err) }) - - t.Run("fetch DutyUniversalProposer", func(t *testing.T) { - duty := core.NewUniversalProposerDuty(slot) - fetch, err := fetcher.New(bmock, func(core.PubKey) string { - return feeRecipientAddr - }) - require.NoError(t, err) - - fetch.RegisterAggSigDB(func(ctx context.Context, duty core.Duty, key core.PubKey) (core.SignedData, error) { - return randaoByPubKey[key], nil - }) - - fetch.Subscribe(func(ctx context.Context, resDuty core.Duty, resDataSet core.UnsignedDataSet) error { - require.Equal(t, duty, resDuty) - require.Len(t, resDataSet, 2) - - dutyDataA := resDataSet[pubkeysByIdx[vIdxA]].(core.VersionedUniversalProposal) - slotA, err := dutyDataA.Slot() - require.NoError(t, err) - require.EqualValues(t, slot, slotA) - require.Equal(t, feeRecipientAddr, fmt.Sprintf("%#x", dutyDataA.Proposal.Capella.Body.ExecutionPayload.FeeRecipient)) - assertRandaoUniversalBlock(t, randaoByPubKey[pubkeysByIdx[vIdxA]].Signature().ToETH2(), dutyDataA) - - dutyDataB := resDataSet[pubkeysByIdx[vIdxB]].(core.VersionedUniversalProposal) - slotB, err := dutyDataB.Slot() - require.NoError(t, err) - require.EqualValues(t, slot, slotB) - require.Equal(t, feeRecipientAddr, fmt.Sprintf("%#x", dutyDataB.Proposal.Capella.Body.ExecutionPayload.FeeRecipient)) - assertRandaoUniversalBlock(t, randaoByPubKey[pubkeysByIdx[vIdxB]].Signature().ToETH2(), dutyDataB) - - return nil - }) - - err = fetch.Fetch(ctx, duty, defSet) - require.NoError(t, err) - }) } func TestFetchSyncContribution(t *testing.T) { @@ -624,21 +588,6 @@ func assertRandaoBlindedBlock(t *testing.T, randao eth2p0.BLSSignature, block co } } -func assertRandaoUniversalBlock(t *testing.T, randao eth2p0.BLSSignature, block core.VersionedUniversalProposal) { - t.Helper() - - if block.Proposal != nil { - p, err := core.NewVersionedProposal(block.Proposal) - require.NoError(t, err) - assertRandao(t, randao, p) - } - if block.BlindedProposal != nil { - p, err := core.NewVersionedBlindedProposal(block.BlindedProposal) - require.NoError(t, err) - assertRandaoBlindedBlock(t, randao, p) - } -} - // blsSigFromHex returns the BLS signature from the input hex signature. func blsSigFromHex(t *testing.T, sig string) eth2p0.BLSSignature { t.Helper() diff --git a/core/signeddata.go b/core/signeddata.go index 8a50755fb..1788f2372 100644 --- a/core/signeddata.go +++ b/core/signeddata.go @@ -27,7 +27,6 @@ import ( var ( _ SignedData = VersionedSignedProposal{} - _ SignedData = VersionedSignedUniversalProposal{} _ SignedData = Attestation{} _ SignedData = Signature{} _ SignedData = SignedVoluntaryExit{} @@ -473,9 +472,6 @@ func (p VersionedSignedBlindedProposal) MarshalJSON() ([]byte, error) { resp, err := json.Marshal(versionedRawBlockJSON{ Version: version, Block: block, - blindedJSON: blindedJSON{ - Blinded: true, - }, }) if err != nil { return nil, errors.Wrap(err, "marshal wrapper") @@ -519,206 +515,10 @@ func (p *VersionedSignedBlindedProposal) UnmarshalJSON(input []byte) error { return nil } -// NewVersionedSignedUniversalProposal validates and returns a new VersionedSignedProposal. -func NewVersionedSignedUniversalProposal(proposal *eth2api.VersionedSignedUniversalProposal) (VersionedSignedUniversalProposal, error) { - if proposal.Proposal != nil { - np, err := NewVersionedSignedProposal(proposal.Proposal) - if err != nil { - return VersionedSignedUniversalProposal{}, err - } - - return VersionedSignedUniversalProposal{ - VersionedSignedUniversalProposal: eth2api.VersionedSignedUniversalProposal{ - Proposal: &np.VersionedSignedProposal, - }, - }, nil - } - if proposal.BlindedProposal != nil { - bp, err := NewVersionedSignedBlindedProposal(proposal.BlindedProposal) - if err != nil { - return VersionedSignedUniversalProposal{}, err - } - - return VersionedSignedUniversalProposal{ - VersionedSignedUniversalProposal: eth2api.VersionedSignedUniversalProposal{ - BlindedProposal: &bp.VersionedSignedBlindedProposal, - }, - }, nil - } - - return VersionedSignedUniversalProposal{}, errors.New("invalid proposal") -} - -// NewPartialVersionedSignedUniversalProposal validates and returns a new partial VersionedSignedUniversalProposal. -func NewPartialVersionedSignedUniversalProposal(proposal *eth2api.VersionedSignedUniversalProposal, shareIdx int) (ParSignedData, error) { - wrap, err := NewVersionedSignedUniversalProposal(proposal) - if err != nil { - return ParSignedData{}, err - } - - return ParSignedData{ - SignedData: wrap, - ShareIdx: shareIdx, - }, nil -} - -// VersionedSignedUniversalProposal is a signed versioned universal proposal and implements SignedData. -type VersionedSignedUniversalProposal struct { - eth2api.VersionedSignedUniversalProposal -} - -func (p VersionedSignedUniversalProposal) Signature() Signature { - if p.Proposal != nil { - np, err := NewVersionedSignedProposal(p.Proposal) - if err != nil { - panic("invalid proposal: " + err.Error()) - } - - return np.Signature() - } - if p.BlindedProposal != nil { - np, err := NewVersionedSignedBlindedProposal(p.BlindedProposal) - if err != nil { - panic("invalid blinded proposal: " + err.Error()) - } - - return np.Signature() - } - - panic("invalid proposal") -} - -func (p VersionedSignedUniversalProposal) SetSignature(sig Signature) (SignedData, error) { - resp, err := p.clone() - if err != nil { - return nil, err - } - - if p.Proposal != nil { - np, err := NewVersionedSignedProposal(p.Proposal) - if err != nil { - return nil, err - } - sd, err := np.SetSignature(sig) - if err != nil { - return nil, err - } - vsp, ok := sd.(VersionedSignedProposal) - if !ok { - return nil, errors.New("invalid proposal") - } - resp.Proposal = &vsp.VersionedSignedProposal - } - if p.BlindedProposal != nil { - np, err := NewVersionedSignedBlindedProposal(p.BlindedProposal) - if err != nil { - return nil, err - } - sd, err := np.SetSignature(sig) - if err != nil { - return nil, err - } - vsbp, ok := sd.(VersionedSignedBlindedProposal) - if !ok { - return nil, errors.New("invalid blinded proposal") - } - resp.BlindedProposal = &vsbp.VersionedSignedBlindedProposal - } - - return resp, nil -} - -func (p VersionedSignedUniversalProposal) MessageRoot() ([32]byte, error) { - if p.Proposal != nil { - np, err := NewVersionedSignedProposal(p.Proposal) - if err != nil { - return [32]byte{}, err - } - - return np.MessageRoot() - } - if p.BlindedProposal != nil { - np, err := NewVersionedSignedBlindedProposal(p.BlindedProposal) - if err != nil { - return [32]byte{}, err - } - - return np.MessageRoot() - } - - return [32]byte{}, errors.New("invalid proposal") -} - -func (p VersionedSignedUniversalProposal) Clone() (SignedData, error) { - return p.clone() -} - -// clone returns a copy of the VersionedSignedBlindedProposal. -// It is similar to Clone that returns the SignedData interface. -func (p VersionedSignedUniversalProposal) clone() (VersionedSignedUniversalProposal, error) { - var resp VersionedSignedUniversalProposal - err := cloneJSONMarshaler(p, &resp) - if err != nil { - return VersionedSignedUniversalProposal{}, errors.Wrap(err, "clone universal proposal") - } - - return resp, nil -} - -func (p VersionedSignedUniversalProposal) MarshalJSON() ([]byte, error) { - if p.Proposal != nil { - np, err := NewVersionedSignedProposal(p.Proposal) - if err != nil { - return nil, err - } - - return np.MarshalJSON() - } - if p.BlindedProposal != nil { - bp, err := NewVersionedSignedBlindedProposal(p.BlindedProposal) - if err != nil { - return nil, err - } - - return bp.MarshalJSON() - } - - return nil, errors.New("invalid proposal") -} - -func (p *VersionedSignedUniversalProposal) UnmarshalJSON(input []byte) error { - var bjson blindedJSON - if err := json.Unmarshal(input, &bjson); err != nil { - return errors.Wrap(err, "unmarshal blinded flag") - } - - if bjson.Blinded { - var bp VersionedSignedBlindedProposal - if err := bp.UnmarshalJSON(input); err != nil { - return err - } - p.BlindedProposal = &bp.VersionedSignedBlindedProposal - } else { - var np VersionedSignedProposal - if err := np.UnmarshalJSON(input); err != nil { - return err - } - p.Proposal = &np.VersionedSignedProposal - } - - return nil -} - -// blindedJSON is a helper type for JSON marshalling of blinded blocks. -type blindedJSON struct { - Blinded bool `json:"blinded,omitempty"` -} - // versionedRawBlockJSON is a custom VersionedSignedBeaconBlock or VersionedSignedBlindedBeaconBlock serialiser. type versionedRawBlockJSON struct { Version eth2util.DataVersion `json:"version"` Block json.RawMessage `json:"block"` - blindedJSON } // NewAttestation is a convenience function that returns a new wrapped attestation. diff --git a/core/signeddata_test.go b/core/signeddata_test.go index 839b696d1..0354183e3 100644 --- a/core/signeddata_test.go +++ b/core/signeddata_test.go @@ -37,20 +37,6 @@ func TestSignedDataSetSignature(t *testing.T) { }, }, }, - { - name: "versioned signed universal proposal", - data: core.VersionedSignedUniversalProposal{ - VersionedSignedUniversalProposal: eth2api.VersionedSignedUniversalProposal{ - Proposal: ð2api.VersionedSignedProposal{ - Version: eth2spec.DataVersionBellatrix, - Bellatrix: &bellatrix.SignedBeaconBlock{ - Message: testutil.RandomBellatrixBeaconBlock(), - Signature: testutil.RandomEth2Signature(), - }, - }, - }, - }, - }, { name: "versioned signed blinded proposal bellatrix", data: core.VersionedSignedBlindedProposal{ @@ -87,20 +73,6 @@ func TestSignedDataSetSignature(t *testing.T) { }, }, }, - { - name: "versioned signed universal proposal deneb", - data: core.VersionedSignedUniversalProposal{ - VersionedSignedUniversalProposal: eth2api.VersionedSignedUniversalProposal{ - BlindedProposal: ð2api.VersionedSignedBlindedProposal{ - Version: eth2spec.DataVersionDeneb, - Deneb: ð2deneb.SignedBlindedBeaconBlock{ - Message: testutil.RandomDenebBlindedBeaconBlock(), - Signature: testutil.RandomEth2Signature(), - }, - }, - }, - }, - }, { name: "signed beacon committee selection", data: testutil.RandomCoreBeaconCommitteeSelection(), diff --git a/core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden b/core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden index 418d4daa0..bb3f4c71d 100644 --- a/core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden +++ b/core/testdata/TestJSONSerialisation_VersionedBlindedProposal.json.golden @@ -453,6 +453,5 @@ "0x18bd1830c7613fac2533e7634d9c3de68ba24d971c81ea87a0e1fe781890e6ae10ad72ec7f3e7b7c093e0e3c7d7f0c3f" ] } - }, - "blinded": true + } } \ No newline at end of file diff --git a/core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden b/core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden index 87b68f000..1b42a05a1 100644 --- a/core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden +++ b/core/testdata/TestJSONSerialisation_VersionedSignedBlindedProposal.json.golden @@ -512,6 +512,5 @@ } }, "signature": "0xd136e45a22f2634dcdce80f368f457d4262844ae50bb6d098aeed272e3192c813e096cf652397f3b3f4b95795d3fd65ab9a164e0040cef446460dc5a51518234d3232eeb2630c1f27612093119ebcfaac8db946a6e4bd6825f27db9f6f6606cd" - }, - "blinded": true + } } \ No newline at end of file diff --git a/core/types.go b/core/types.go index c7b1719c9..940cdc72f 100644 --- a/core/types.go +++ b/core/types.go @@ -39,10 +39,9 @@ const ( DutyPrepareSyncContribution DutyType = 11 DutySyncContribution DutyType = 12 DutyInfoSync DutyType = 13 - DutyUniversalProposer DutyType = 14 // Only ever append new types here... - dutySentinel DutyType = 15 // Must always be last + dutySentinel DutyType = 14 // Must always be last ) func (d DutyType) Valid() bool { @@ -65,7 +64,6 @@ func (d DutyType) String() string { DutyPrepareSyncContribution: "prepare_sync_contribution", DutySyncContribution: "sync_contribution", DutyInfoSync: "info_sync", - DutyUniversalProposer: "universal_proposer", }[d] } @@ -144,20 +142,6 @@ func NewProposerDuty(slot uint64) Duty { } } -// NewUniversalProposerDuty returns a new universal proposer duty. -// It is a convenience function that is slightly more readable -// and concise than the struct literal equivalent: -// -// core.Duty{Slot: slot, Type: core.DutyUniversalProposer} -// vs -// core.NewUniversalProposerDuty(slot) -func NewUniversalProposerDuty(slot uint64) Duty { - return Duty{ - Slot: slot, - Type: DutyUniversalProposer, - } -} - // NewVoluntaryExit returns a new voluntary exit duty. It is a convenience function that is // slightly more readable and concise than the struct literal equivalent: // diff --git a/core/types_test.go b/core/types_test.go index ff8ab1a12..5af985e0d 100644 --- a/core/types_test.go +++ b/core/types_test.go @@ -28,10 +28,9 @@ func TestBackwardsCompatability(t *testing.T) { require.EqualValues(t, 11, core.DutyPrepareSyncContribution) require.EqualValues(t, 12, core.DutySyncContribution) require.EqualValues(t, 13, core.DutyInfoSync) - require.EqualValues(t, 14, core.DutyUniversalProposer) // Add more types here. - const sentinel = core.DutyType(15) + const sentinel = core.DutyType(14) for i := core.DutyUnknown; i <= sentinel; i++ { if i == core.DutyUnknown { require.False(t, i.Valid()) @@ -67,10 +66,3 @@ func TestWithDutySpanCtx(t *testing.T) { require.True(t, span2.SpanContext().IsValid()) require.True(t, span2.SpanContext().IsSampled()) } - -func TestNewUniversalProposerDuty(t *testing.T) { - duty := core.NewUniversalProposerDuty(1) - - require.Equal(t, core.DutyUniversalProposer, duty.Type) - require.Equal(t, uint64(1), duty.Slot) -} diff --git a/core/unsigneddata.go b/core/unsigneddata.go index 4522f29b4..0e2d2c394 100644 --- a/core/unsigneddata.go +++ b/core/unsigneddata.go @@ -26,7 +26,6 @@ var ( _ UnsignedData = AggregatedAttestation{} _ UnsignedData = VersionedProposal{} _ UnsignedData = VersionedBlindedProposal{} - _ UnsignedData = VersionedUniversalProposal{} _ UnsignedData = SyncContribution{} // Some types also support SSZ marshalling and unmarshalling. @@ -335,9 +334,6 @@ func (p VersionedBlindedProposal) MarshalJSON() ([]byte, error) { resp, err := json.Marshal(versionedRawBlockJSON{ Version: version, Block: block, - blindedJSON: blindedJSON{ - Blinded: true, - }, }) if err != nil { return nil, errors.Wrap(err, "marshal wrapper") @@ -381,71 +377,6 @@ func (p *VersionedBlindedProposal) UnmarshalJSON(input []byte) error { return nil } -// NewVersionedUniversalProposal validates and returns a new wrapped VersionedUniversalProposal. -func NewVersionedUniversalProposal(proposal *eth2api.VersionedUniversalProposal) (VersionedUniversalProposal, error) { - return VersionedUniversalProposal{VersionedUniversalProposal: *proposal}, nil -} - -// VersionedUniversalProposal wraps the eth2 versioned proposal and implements UnsignedData. -type VersionedUniversalProposal struct { - eth2api.VersionedUniversalProposal -} - -func (p VersionedUniversalProposal) Clone() (UnsignedData, error) { - var resp VersionedUniversalProposal - err := cloneJSONMarshaler(p, &resp) - if err != nil { - return nil, errors.Wrap(err, "clone universal proposal") - } - - return resp, nil -} - -func (p VersionedUniversalProposal) MarshalJSON() ([]byte, error) { - if p.Proposal != nil { - fp, err := NewVersionedProposal(p.Proposal) - if err != nil { - return nil, err - } - - return fp.MarshalJSON() - } - - if p.BlindedProposal != nil { - bp, err := NewVersionedBlindedProposal(p.BlindedProposal) - if err != nil { - return nil, err - } - - return bp.MarshalJSON() - } - - return nil, errors.New("no full or blinded block") -} - -func (p *VersionedUniversalProposal) UnmarshalJSON(input []byte) error { - var bjson blindedJSON - if err := json.Unmarshal(input, &bjson); err != nil { - return errors.Wrap(err, "unmarshal blinded flag") - } - - if bjson.Blinded { - var bp VersionedBlindedProposal - if err := bp.UnmarshalJSON(input); err != nil { - return err - } - p.BlindedProposal = &bp.VersionedBlindedProposal - } else { - var fp VersionedProposal - if err := fp.UnmarshalJSON(input); err != nil { - return err - } - p.Proposal = &fp.VersionedProposal - } - - return nil -} - // NewSyncContribution returns a new SyncContribution. func NewSyncContribution(c *altair.SyncCommitteeContribution) SyncContribution { return SyncContribution{SyncCommitteeContribution: *c} diff --git a/core/unsigneddata_test.go b/core/unsigneddata_test.go index b836bc1ab..083a6e105 100644 --- a/core/unsigneddata_test.go +++ b/core/unsigneddata_test.go @@ -5,7 +5,6 @@ package core_test import ( "testing" - eth2api "github.com/attestantio/go-eth2-client/api" "github.com/stretchr/testify/require" "github.com/obolnetwork/charon/core" @@ -37,14 +36,6 @@ func TestUnsignedDataClone(t *testing.T) { name: "versioned blinded beacon block capella", data: testutil.RandomCapellaVersionedBlindedProposal(), }, - { - name: "versioned beacon block capella as universal proposal", - data: versionedProposalToUniversal(t, testutil.RandomCapellaCoreVersionedProposal()), - }, - { - name: "versioned blinded beacon block capella as universal proposal", - data: versionedBlindedProposalToUniversal(t, testutil.RandomCapellaVersionedBlindedProposal()), - }, { name: "aggregated attestation", data: core.NewAggregatedAttestation(testutil.RandomAttestation()), @@ -63,23 +54,3 @@ func TestUnsignedDataClone(t *testing.T) { }) } } - -func versionedProposalToUniversal(t *testing.T, p core.VersionedProposal) core.VersionedUniversalProposal { - t.Helper() - - return core.VersionedUniversalProposal{ - VersionedUniversalProposal: eth2api.VersionedUniversalProposal{ - Proposal: &p.VersionedProposal, - }, - } -} - -func versionedBlindedProposalToUniversal(t *testing.T, p core.VersionedBlindedProposal) core.VersionedUniversalProposal { - t.Helper() - - return core.VersionedUniversalProposal{ - VersionedUniversalProposal: eth2api.VersionedUniversalProposal{ - BlindedProposal: &p.VersionedBlindedProposal, - }, - } -} diff --git a/go.mod b/go.mod index 4c703e9d9..7710e3995 100644 --- a/go.mod +++ b/go.mod @@ -200,6 +200,3 @@ require ( // We're replacing kryptology with our own fork, which fixes dependencies' security vulnerabilities. replace github.com/coinbase/kryptology => github.com/ObolNetwork/kryptology v0.0.0-20231016091344-eed023b6cac8 - -// We're replacing go-eth2-client with our own fork, which adds UniversalProposel model for produceBlockV3 endpoint. -replace github.com/attestantio/go-eth2-client v0.19.10 => github.com/obolNetwork/go-eth2-client v0.0.0-20240228154246-66d3d0ccd2e1 diff --git a/go.sum b/go.sum index 3da2b1414..c66ef8691 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/ObolNetwork/kryptology v0.0.0-20231016091344-eed023b6cac8/go.mod h1:q github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/attestantio/go-eth2-client v0.19.10 h1:NLs9mcBvZpBTZ3du7Ey2NHQoj8d3UePY7pFBXX6C6qs= +github.com/attestantio/go-eth2-client v0.19.10/go.mod h1:TTz7YF6w4z6ahvxKiHuGPn6DbQn7gH6HPuWm/DEQeGE= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= @@ -368,8 +370,6 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/obolNetwork/go-eth2-client v0.0.0-20240228154246-66d3d0ccd2e1 h1:2mSMLPu6raLaYeUCX0M5Rho94G/835Jo6L66VjrA0jI= -github.com/obolNetwork/go-eth2-client v0.0.0-20240228154246-66d3d0ccd2e1/go.mod h1:TTz7YF6w4z6ahvxKiHuGPn6DbQn7gH6HPuWm/DEQeGE= github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= diff --git a/testutil/beaconmock/beaconmock.go b/testutil/beaconmock/beaconmock.go index f8d9739b2..f2f3d9e84 100644 --- a/testutil/beaconmock/beaconmock.go +++ b/testutil/beaconmock/beaconmock.go @@ -118,7 +118,6 @@ type Mock struct { NodePeerCountFunc func(ctx context.Context) (int, error) ProposalFunc func(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2api.VersionedProposal, error) BlindedProposalFunc func(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.VersionedBlindedProposal, error) - UniversalProposalFunc func(ctx context.Context, opts *eth2api.UniversalProposalOpts) (*eth2api.VersionedUniversalProposal, error) SignedBeaconBlockFunc func(ctx context.Context, blockID string) (*eth2spec.VersionedSignedBeaconBlock, error) ProposerDutiesFunc func(context.Context, eth2p0.Epoch, []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) SubmitAttestationsFunc func(context.Context, []*eth2p0.Attestation) error @@ -182,15 +181,6 @@ func (m Mock) Proposal(ctx context.Context, opts *eth2api.ProposalOpts) (*eth2ap return wrapResponse(block), nil } -func (m Mock) UniversalProposal(ctx context.Context, opts *eth2api.UniversalProposalOpts) (*eth2api.Response[*eth2api.VersionedUniversalProposal], error) { - block, err := m.UniversalProposalFunc(ctx, opts) - if err != nil { - return nil, err - } - - return wrapResponse(block), nil -} - func (m Mock) BlindedProposal(ctx context.Context, opts *eth2api.BlindedProposalOpts) (*eth2api.Response[*eth2api.VersionedBlindedProposal], error) { block, err := m.BlindedProposalFunc(ctx, opts) if err != nil { diff --git a/testutil/beaconmock/beaconmock_fuzz.go b/testutil/beaconmock/beaconmock_fuzz.go index 263743d8b..5ce7396e4 100644 --- a/testutil/beaconmock/beaconmock_fuzz.go +++ b/testutil/beaconmock/beaconmock_fuzz.go @@ -136,13 +136,6 @@ func WithBeaconMockFuzzer() Option { return block, nil } - mock.UniversalProposalFunc = func(ctx context.Context, opts *eth2api.UniversalProposalOpts) (*eth2api.VersionedUniversalProposal, error) { - var block *eth2api.VersionedUniversalProposal - fuzz.New().Fuzz(&block) - - return block, nil - } - mock.NodePeerCountFunc = func(context.Context) (int, error) { var count int fuzz.New().Fuzz(&count) diff --git a/testutil/beaconmock/options.go b/testutil/beaconmock/options.go index 4d74d7d9d..705e5d612 100644 --- a/testutil/beaconmock/options.go +++ b/testutil/beaconmock/options.go @@ -497,19 +497,6 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo return block, nil }, - UniversalProposalFunc: func(ctx context.Context, opts *eth2api.UniversalProposalOpts) (*eth2api.VersionedUniversalProposal, error) { - block := ð2api.VersionedUniversalProposal{ - Proposal: ð2api.VersionedProposal{ - Version: eth2spec.DataVersionCapella, - Capella: testutil.RandomCapellaBeaconBlock(), - }, - } - block.Proposal.Capella.Slot = opts.Slot - block.Proposal.Capella.Body.RANDAOReveal = opts.RandaoReveal - block.Proposal.Capella.Body.Graffiti = opts.Graffiti - - return block, nil - }, SignedBeaconBlockFunc: func(_ context.Context, blockID string) (*eth2spec.VersionedSignedBeaconBlock, error) { return testutil.RandomCapellaVersionedSignedBeaconBlock(), nil // Note the slot is probably wrong. }, diff --git a/testutil/validatormock/component.go b/testutil/validatormock/component.go index 261d59774..c808318e2 100644 --- a/testutil/validatormock/component.go +++ b/testutil/validatormock/component.go @@ -287,10 +287,6 @@ func (m *Component) runDuty(ctx context.Context, duty core.Duty) error { if err = ProposeBlindedBlock(ctx, eth2Cl, m.signFunc, eth2Slot); err != nil { return err } - case core.DutyUniversalProposer: - if err = ProposeUniversalBlock(ctx, eth2Cl, m.signFunc, eth2Slot); err != nil { - return err - } case core.DutyBuilderRegistration: if !m.builderAPI { return nil diff --git a/testutil/validatormock/propose.go b/testutil/validatormock/propose.go index 1324da4e2..386db6402 100644 --- a/testutil/validatormock/propose.go +++ b/testutil/validatormock/propose.go @@ -31,17 +31,18 @@ import ( // SignFunc abstract signing done by the validator client. type SignFunc func(pubshare eth2p0.BLSPubKey, data []byte) (eth2p0.BLSSignature, error) -func getRandao(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, +// ProposeBlock proposes block for the given slot. +func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, slot eth2p0.Slot, -) (eth2p0.BLSSignature, eth2p0.BLSPubKey, eth2p0.Epoch, error) { +) error { valMap, err := eth2Cl.ActiveValidators(ctx) if err != nil { - return eth2p0.BLSSignature{}, eth2p0.BLSPubKey{}, 0, err + return err } slotsPerEpoch, err := eth2Cl.SlotsPerEpoch(ctx) if err != nil { - return eth2p0.BLSSignature{}, eth2p0.BLSPubKey{}, 0, err + return err } epoch := eth2p0.Epoch(uint64(slot) / slotsPerEpoch) @@ -56,7 +57,7 @@ func getRandao(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, } eth2Resp, err := eth2Cl.ProposerDuties(ctx, opts) if err != nil { - return eth2p0.BLSSignature{}, eth2p0.BLSPubKey{}, 0, err + return err } duties := eth2Resp.Data @@ -69,83 +70,27 @@ func getRandao(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, } if slotProposer == nil { - return eth2p0.BLSSignature{}, eth2p0.BLSPubKey{}, 0, nil + return nil } + var ( + pubkey eth2p0.BLSPubKey + block *eth2api.VersionedProposal + ) + pubkey = slotProposer.PubKey + // Create randao reveal to propose block randaoSigRoot, err := eth2util.SignedEpoch{Epoch: epoch}.HashTreeRoot() - if err != nil { - return eth2p0.BLSSignature{}, eth2p0.BLSPubKey{}, 0, err - } - - randaoSigData, err := signing.GetDataRoot(ctx, eth2Cl, signing.DomainRandao, epoch, randaoSigRoot) - if err != nil { - return eth2p0.BLSSignature{}, eth2p0.BLSPubKey{}, 0, err - } - - randao, err := signFunc(slotProposer.PubKey, randaoSigData[:]) - if err != nil { - return eth2p0.BLSSignature{}, eth2p0.BLSPubKey{}, 0, err - } - - return randao, slotProposer.PubKey, epoch, nil -} - -// ProposeUniversalBlock proposes universal block for the given slot. -func ProposeUniversalBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, - slot eth2p0.Slot, -) error { - randao, pubkey, epoch, err := getRandao(ctx, eth2Cl, signFunc, slot) if err != nil { return err } - // Get Unsigned beacon block with given randao and slot - proposalOpts := ð2api.UniversalProposalOpts{ - Slot: slot, - RandaoReveal: randao, - } - eth2ProposalResp, err := eth2Cl.UniversalProposal(ctx, proposalOpts) - if err != nil { - return errors.Wrap(err, "vmock beacon block proposal") - } - - block := eth2ProposalResp.Data - if block == nil { - return errors.New("block not found") - } - - // Sign beacon block - blockSigRoot, err := block.Root() - if err != nil { - return err - } - - blockSigData, err := signing.GetDataRoot(ctx, eth2Cl, signing.DomainBeaconProposer, epoch, blockSigRoot) - if err != nil { - return err - } - - sig, err := signFunc(pubkey, blockSigData[:]) + randaoSigData, err := signing.GetDataRoot(ctx, eth2Cl, signing.DomainRandao, epoch, randaoSigRoot) if err != nil { return err } - if block.Proposal != nil { - return submitVersionedSignedProposal(ctx, sig, eth2Cl, block.Proposal) - } - if block.BlindedProposal != nil { - return submitVersionedSignedBlindedProposal(ctx, sig, eth2Cl, block.BlindedProposal) - } - - return errors.New("invalid block") -} - -// ProposeBlock proposes block for the given slot. -func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, - slot eth2p0.Slot, -) error { - randao, pubkey, epoch, err := getRandao(ctx, eth2Cl, signFunc, slot) + randao, err := signFunc(slotProposer.PubKey, randaoSigData[:]) if err != nil { return err } @@ -159,8 +104,8 @@ func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc if err != nil { return errors.Wrap(err, "vmock beacon block proposal") } + block = eth2ProposalResp.Data - block := eth2ProposalResp.Data if block == nil { return errors.New("block not found") } @@ -181,12 +126,6 @@ func ProposeBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc return err } - return submitVersionedSignedProposal(ctx, sig, eth2Cl, block) -} - -func submitVersionedSignedProposal(ctx context.Context, sig eth2p0.BLSSignature, - eth2Cl eth2wrap.Client, block *eth2api.VersionedProposal, -) error { // Create signed beacon block proposal. signedBlock := new(eth2api.VersionedSignedProposal) signedBlock.Version = block.Version @@ -231,7 +170,63 @@ func submitVersionedSignedProposal(ctx context.Context, sig eth2p0.BLSSignature, func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, slot eth2p0.Slot, ) error { - randao, pubkey, epoch, err := getRandao(ctx, eth2Cl, signFunc, slot) + valMap, err := eth2Cl.ActiveValidators(ctx) + if err != nil { + return err + } + + slotsPerEpoch, err := eth2Cl.SlotsPerEpoch(ctx) + if err != nil { + return err + } + + epoch := eth2p0.Epoch(uint64(slot) / slotsPerEpoch) + + var indexes []eth2p0.ValidatorIndex + for index := range valMap { + indexes = append(indexes, index) + } + + opts := ð2api.ProposerDutiesOpts{ + Epoch: epoch, + Indices: indexes, + } + eth2Resp, err := eth2Cl.ProposerDuties(ctx, opts) + if err != nil { + return err + } + duties := eth2Resp.Data + + var slotProposer *eth2v1.ProposerDuty + for _, duty := range duties { + if duty.Slot == slot { + slotProposer = duty + break + } + } + + if slotProposer == nil { + return nil + } + + var ( + pubkey eth2p0.BLSPubKey + block *eth2api.VersionedBlindedProposal + ) + pubkey = slotProposer.PubKey + + // Create randao reveal to propose block + randaoSigRoot, err := eth2util.SignedEpoch{Epoch: epoch}.HashTreeRoot() + if err != nil { + return err + } + + randaoSigData, err := signing.GetDataRoot(ctx, eth2Cl, signing.DomainRandao, epoch, randaoSigRoot) + if err != nil { + return err + } + + randao, err := signFunc(slotProposer.PubKey, randaoSigData[:]) if err != nil { return err } @@ -245,8 +240,8 @@ func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc S if err != nil { return errors.Wrap(err, "vmock blinded beacon block proposal") } + block = proposalResp.Data - block := proposalResp.Data if block == nil { return errors.New("block not found") } @@ -267,12 +262,6 @@ func ProposeBlindedBlock(ctx context.Context, eth2Cl eth2wrap.Client, signFunc S return err } - return submitVersionedSignedBlindedProposal(ctx, sig, eth2Cl, block) -} - -func submitVersionedSignedBlindedProposal(ctx context.Context, sig eth2p0.BLSSignature, - eth2Cl eth2wrap.Client, block *eth2api.VersionedBlindedProposal, -) error { // create signed beacon block signedBlock := new(eth2api.VersionedSignedBlindedProposal) signedBlock.Version = block.Version diff --git a/testutil/validatormock/propose_test.go b/testutil/validatormock/propose_test.go index 9e239823d..1726b23ef 100644 --- a/testutil/validatormock/propose_test.go +++ b/testutil/validatormock/propose_test.go @@ -205,54 +205,6 @@ func TestProposeBlindedBlock(t *testing.T) { require.NoError(t, err) } -func TestProposeUniversalBlock(t *testing.T) { - ctx := context.Background() - - // Configure beacon mock - valSet := beaconmock.ValidatorSetA - beaconMock, err := beaconmock.New( - beaconmock.WithValidatorSet(valSet), - beaconmock.WithDeterministicProposerDuties(0), - ) - require.NoError(t, err) - - // Signature stub function - signFunc := func(key eth2p0.BLSPubKey, _ []byte) (eth2p0.BLSSignature, error) { - var sig eth2p0.BLSSignature - copy(sig[:], key[:]) - - return sig, nil - } - - slotsPerEpoch, err := beaconMock.SlotsPerEpoch(ctx) - require.NoError(t, err) - - block := testutil.RandomPhase0BeaconBlock() - block.Slot = eth2p0.Slot(slotsPerEpoch) - - mockVAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - testResponse := []byte(`{"version":"phase0","data":`) - blockJSON, err := block.MarshalJSON() - require.NoError(t, err) - - testResponse = append(testResponse, blockJSON...) - testResponse = append(testResponse, []byte(`}`)...) - require.NoError(t, err) - - _, _ = w.Write(testResponse) - })) - defer mockVAPI.Close() - - provider := addrWrap{ - Client: beaconMock, - addr: mockVAPI.URL, - } - - // Call propose block function - err = validatormock.ProposeUniversalBlock(ctx, provider, signFunc, eth2p0.Slot(slotsPerEpoch)) - require.NoError(t, err) -} - type addrWrap struct { eth2wrap.Client addr string