Skip to content

Commit

Permalink
Aggregations fixes and tests updates
Browse files Browse the repository at this point in the history
  • Loading branch information
KaloyanTanev committed Jan 27, 2025
1 parent b5a9676 commit 461f76b
Show file tree
Hide file tree
Showing 23 changed files with 301 additions and 160 deletions.
2 changes: 1 addition & 1 deletion core/parsigex/parsigex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func TestParSigExVerifier(t *testing.T) {
sigData, err := signing.GetDataRoot(ctx, bmock, signing.DomainAggregateAndProof, epoch, sigRoot)
require.NoError(t, err)
agg.Deneb.Signature = sign(sigData[:])
data := core.NewPartialSignedAggregateAndProof(agg, shareIdx)
data := core.NewPartialVersionedSignedAggregateAndProof(agg, shareIdx)

require.NoError(t, verifyFunc(ctx, core.NewAggregatorDuty(slot), pubkey, data))
})
Expand Down
6 changes: 3 additions & 3 deletions core/proto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func TestParSignedData(t *testing.T) {

func TestParSignedDataFromProtoErrors(t *testing.T) {
parSig1 := core.ParSignedData{
SignedData: core.VersionedSignedAggregateAndProof{*testutil.RandomDenebVersionedSignedAggregateAndProof()},
SignedData: core.SyncCommitteeSelection{*testutil.RandomSyncCommitteeSelection()},
ShareIdx: rand.Intn(100),
}

Expand All @@ -204,7 +204,7 @@ func TestParSignedDataFromProtoErrors(t *testing.T) {
require.ErrorContains(t, err, "unsupported duty type")

_, err = core.ParSignedDataFromProto(core.DutyProposer, pb1)
require.ErrorContains(t, err, "unknown data version")
require.ErrorContains(t, err, "unknown version")

_, err = core.ParSignedDataFromProto(core.DutyBuilderProposer, pb1)
require.ErrorIs(t, err, core.ErrDeprecatedDutyBuilderProposer)
Expand Down Expand Up @@ -246,7 +246,7 @@ func randomSignedData(t *testing.T) map[core.DutyType]core.SignedData {
core.DutyRandao: core.SignedRandao{SignedEpoch: eth2util.SignedEpoch{Epoch: testutil.RandomEpoch(), Signature: testutil.RandomEth2Signature()}},
core.DutyProposer: testutil.RandomBellatrixCoreVersionedSignedProposal(),
core.DutyPrepareAggregator: testutil.RandomCoreBeaconCommitteeSelection(),
core.DutyAggregator: core.NewSignedAggregateAndProof(testutil.RandomDenebVersionedSignedAggregateAndProof()),
core.DutyAggregator: core.NewVersionedSignedAggregateAndProof(testutil.RandomDenebVersionedSignedAggregateAndProof()),
core.DutyPrepareSyncContribution: core.NewSyncCommitteeSelection(testutil.RandomSyncCommitteeSelection()),
core.DutySyncContribution: core.NewSignedSyncContributionAndProof(testutil.RandomSignedSyncContributionAndProof()),
}
Expand Down
10 changes: 5 additions & 5 deletions core/signeddata.go
Original file line number Diff line number Diff line change
Expand Up @@ -1173,15 +1173,15 @@ func (s *SyncCommitteeSelection) UnmarshalJSON(input []byte) error {
return s.SyncCommitteeSelection.UnmarshalJSON(input)
}

// NewSignedAggregateAndProof is a convenience function which returns a new signed SignedAggregateAndProof.
func NewSignedAggregateAndProof(data *eth2spec.VersionedSignedAggregateAndProof) VersionedSignedAggregateAndProof {
// NewVersionedSignedAggregateAndProof is a convenience function which returns a new signed VersionedSignedAggregateAndProof.
func NewVersionedSignedAggregateAndProof(data *eth2spec.VersionedSignedAggregateAndProof) VersionedSignedAggregateAndProof {
return VersionedSignedAggregateAndProof{VersionedSignedAggregateAndProof: *data}
}

// NewPartialSignedAggregateAndProof is a convenience function which returns a new partially signed SignedAggregateAndProof.
func NewPartialSignedAggregateAndProof(data *eth2spec.VersionedSignedAggregateAndProof, shareIdx int) ParSignedData {
// NewPartialVersionedSignedAggregateAndProof is a convenience function which returns a new partially signed VersionedSignedAggregateAndProof.
func NewPartialVersionedSignedAggregateAndProof(data *eth2spec.VersionedSignedAggregateAndProof, shareIdx int) ParSignedData {

Check warning on line 1182 in core/signeddata.go

View check run for this annotation

Codecov / codecov/patch

core/signeddata.go#L1182

Added line #L1182 was not covered by tests
return ParSignedData{
SignedData: NewSignedAggregateAndProof(data),
SignedData: NewVersionedSignedAggregateAndProof(data),

Check warning on line 1184 in core/signeddata.go

View check run for this annotation

Codecov / codecov/patch

core/signeddata.go#L1184

Added line #L1184 was not covered by tests
ShareIdx: shareIdx,
}
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"version": 5,
"attestation": {
"aggregation_bits": "0x0272908d45b01601",
"data": {
"slot": "3748136313440833973",
"index": "10527063875261316388",
"beacon_block_root": "0x5f6c6bb64a52fa1a95e2bdff2aea5190ce067ad5d23f96d5ce92f83e0212d307",
"source": {
"epoch": "11487309897857773744",
"root": "0x49b01b83b78e64fc147e5086ae7c1ac5bbb6496af67041b0d88158d69078e3e2"
},
"target": {
"epoch": "2405710843726920900",
"root": "0x141c7cfe1c0ef0c2f60c29616c2f6b3a805e91ebdedc8fef611e1d079aa67a62"
}
},
"signature": "0x6910c8ea580e905fda113b925adfac8d80ebb68deac0c0d6cb9aa138c60f34218fefbffdf6e04b99c493c785f588d20e8521bdc94684152c509ad47e009399b5de04763e89ef5dd57558ad80535cb99835d61d2c5add5afb4d30b84e5bbd988c",
"committee_bits": "0xff00000000000000"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"version": 5,
"aggregate_and_proof": {
"message": {
"aggregator_index": "12258969221770119542",
"aggregate": {
"aggregation_bits": "0x58485fe3352bc5b501",
"data": {
"slot": "5480206018969903199",
"index": "3810777494496647276",
"beacon_block_root": "0xf11f99ef25258727c8b2922e22f5563d39490544d0ec4c0e68f23b572665b0e6",
"source": {
"epoch": "4405833319574080176",
"root": "0xfd4ffbf4ebe0530c03f2ecd45fac9d4aef1d6a649ec7799f34798eb91ff4c4fe"
},
"target": {
"epoch": "9599321949314998812",
"root": "0x21819c51945e7ed3df1fb0b5a4e0e895804813d1f4a80680595fb94b57636910"
}
},
"signature": "0x45bb08f5197bb91ffb894a8e40f9a837cbbccd54915ca94d509daa426fe2a33e1b669111cc4ff4fcc5071606dc666e998b5982ab0f52cf75924a308bcb99683bccc2813229bf922aaf112694262a4c953678a238749d8e791fa82ad773e2bb97",
"committee_bits": "0xff00000000000000"
},
"selection_proof": "0xfdb4c49a3f8cff429c026a404df8b9f7305d8a820f2f1fa5a1350874452a54bc1d4d3021afb9a99adb32f0e7586d114eb003386bd4374680a26a00f0d6ed086dd4369f0897c9e5d32d3df8099046f2bbed9d544205208fe1a216b739392c2fec"
},
"signature": "0x7d6f657ed2087a246b2a63f812829816a3019101a49a6a268bc71e1e9867ae25640f4e158921c54009b7b78713ebabe0e6f188aab1968170cf910311c84e1469a0aa9696c7c6a5507bcb0400cf695e3ebc1b8668a081e3435809b8c533f091d7"
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion core/tracker/inclusion.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ func checkAggregationInclusion(sub submission, block block) (bool, error) {
if err != nil {
return false, errors.Wrap(err, "get attestation aggregation bits")
}
subBits := sub.Data.(*core.VersionedSignedAggregateAndProof).AggregationBits()
subBits := sub.Data.(core.VersionedSignedAggregateAndProof).AggregationBits()
ok, err = attAggregationBits.Contains(subBits)
if err != nil {
return false, errors.Wrap(err, "check aggregation bits",
Expand Down
2 changes: 1 addition & 1 deletion core/tracker/inclusion_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func TestInclusion(t *testing.T) {
require.NoError(t, err)
err = incl.Submitted(att1Duty, "", incl1, 0)
require.NoError(t, err)
err = incl.Submitted(agg2Duty, "", core.NewSignedAggregateAndProof(agg2), 0)
err = incl.Submitted(agg2Duty, "", core.NewVersionedSignedAggregateAndProof(agg2), 0)
require.NoError(t, err)
incl3, err := core.NewVersionedAttestation(att3)
require.NoError(t, err)
Expand Down
64 changes: 57 additions & 7 deletions core/unsigneddata.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import (
"github.com/attestantio/go-eth2-client/spec/altair"
"github.com/attestantio/go-eth2-client/spec/bellatrix"
"github.com/attestantio/go-eth2-client/spec/capella"
eth2e "github.com/attestantio/go-eth2-client/spec/electra"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
ssz "github.com/ferranbt/fastssz"

"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/z"
"github.com/obolnetwork/charon/eth2util"
)

Expand Down Expand Up @@ -165,9 +167,9 @@ func (a VersionedAggregatedAttestation) MarshalJSON() ([]byte, error) {
return nil, errors.Wrap(err, "convert version")
}

Check warning on line 168 in core/unsigneddata.go

View check run for this annotation

Codecov / codecov/patch

core/unsigneddata.go#L167-L168

Added lines #L167 - L168 were not covered by tests

resp, err := json.Marshal(versionedRawAggregateAndProofJSON{
Version: version,
AggregateAndProof: aggregatedAttestation,
resp, err := json.Marshal(versionedRawAttestationJSON{
Version: version,
Attestation: aggregatedAttestation,
})
if err != nil {
return nil, errors.Wrap(err, "marshal wrapper")
Expand Down Expand Up @@ -197,12 +199,60 @@ func (a VersionedAggregatedAttestation) HashTreeRoot() ([32]byte, error) {
}

func (a *VersionedAggregatedAttestation) UnmarshalJSON(input []byte) error {
var att eth2spec.VersionedAttestation
if err := json.Unmarshal(input, &att); err != nil {
return errors.Wrap(err, "unmarshal aggregated attestation")
var raw versionedRawAttestationJSON
if err := json.Unmarshal(input, &raw); err != nil {
return errors.Wrap(err, "unmarshal attestation")
}

Check warning on line 205 in core/unsigneddata.go

View check run for this annotation

Codecov / codecov/patch

core/unsigneddata.go#L204-L205

Added lines #L204 - L205 were not covered by tests

resp := eth2spec.VersionedAttestation{Version: raw.Version.ToETH2()}
switch resp.Version {
case eth2spec.DataVersionPhase0:
att := new(eth2p0.Attestation)
err := json.Unmarshal(raw.Attestation, &att)
if err != nil {
return errors.Wrap(err, "unmarshal phase0")
}

Check warning on line 214 in core/unsigneddata.go

View check run for this annotation

Codecov / codecov/patch

core/unsigneddata.go#L213-L214

Added lines #L213 - L214 were not covered by tests
resp.Phase0 = att
case eth2spec.DataVersionAltair:
att := new(eth2p0.Attestation)
err := json.Unmarshal(raw.Attestation, &att)
if err != nil {
return errors.Wrap(err, "unmarshal altair")
}
resp.Altair = att
case eth2spec.DataVersionBellatrix:
att := new(eth2p0.Attestation)
err := json.Unmarshal(raw.Attestation, &att)
if err != nil {
return errors.Wrap(err, "unmarshal bellatrix")
}
resp.Bellatrix = att
case eth2spec.DataVersionCapella:
att := new(eth2p0.Attestation)
err := json.Unmarshal(raw.Attestation, &att)
if err != nil {
return errors.Wrap(err, "unmarshal capella")
}
resp.Capella = att

Check warning on line 236 in core/unsigneddata.go

View check run for this annotation

Codecov / codecov/patch

core/unsigneddata.go#L216-L236

Added lines #L216 - L236 were not covered by tests
case eth2spec.DataVersionDeneb:
att := new(eth2p0.Attestation)
err := json.Unmarshal(raw.Attestation, &att)
if err != nil {
return errors.Wrap(err, "unmarshal deneb")
}

Check warning on line 242 in core/unsigneddata.go

View check run for this annotation

Codecov / codecov/patch

core/unsigneddata.go#L241-L242

Added lines #L241 - L242 were not covered by tests
resp.Deneb = att
case eth2spec.DataVersionElectra:
att := new(eth2e.Attestation)
err := json.Unmarshal(raw.Attestation, &att)
if err != nil {
return errors.Wrap(err, "unmarshal electra")
}

Check warning on line 249 in core/unsigneddata.go

View check run for this annotation

Codecov / codecov/patch

core/unsigneddata.go#L248-L249

Added lines #L248 - L249 were not covered by tests
resp.Electra = att
default:
return errors.New("unknown attestation version", z.Str("version", a.Version.String()))

Check warning on line 252 in core/unsigneddata.go

View check run for this annotation

Codecov / codecov/patch

core/unsigneddata.go#L251-L252

Added lines #L251 - L252 were not covered by tests
}

*a = VersionedAggregatedAttestation{VersionedAttestation: att}
a.VersionedAttestation = resp

return nil
}
Expand Down
45 changes: 35 additions & 10 deletions core/validatorapi/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/attestantio/go-eth2-client/spec/altair"
"github.com/attestantio/go-eth2-client/spec/bellatrix"
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/attestantio/go-eth2-client/spec/electra"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
ssz "github.com/ferranbt/fastssz"
"github.com/gorilla/mux"
Expand Down Expand Up @@ -208,13 +209,13 @@ func NewRouter(ctx context.Context, h Handler, eth2Cl eth2wrap.Client, builderEn
},
{
Name: "aggregate_attestation",
Path: "/eth/v1/validator/aggregate_attestation",
Path: "/eth/v2/validator/aggregate_attestation",
Handler: aggregateAttestation(h),
Methods: []string{http.MethodGet},
},
{
Name: "submit_aggregate_and_proofs",
Path: "/eth/v1/validator/aggregate_and_proofs",
Path: "/eth/v2/validator/aggregate_and_proofs",
Handler: submitAggregateAttestations(h),
Methods: []string{http.MethodPost},
},
Expand Down Expand Up @@ -1030,18 +1031,42 @@ func aggregateAttestation(p eth2client.AggregateAttestationProvider) handlerFunc

func submitAggregateAttestations(s eth2client.AggregateAttestationsSubmitter) handlerFunc {
return func(ctx context.Context, _ map[string]string, _ url.Values, typ contentType, body []byte) (any, http.Header, error) {
var aggs *eth2api.SubmitAggregateAttestationsOpts
err := unmarshal(typ, body, &aggs)
if err != nil {
return nil, nil, errors.Wrap(err, "unmarshal signed aggregate and proofs")
aggs := []*eth2spec.VersionedSignedAggregateAndProof{}

denebAggs := new([]eth2p0.SignedAggregateAndProof)
err := unmarshal(typ, body, denebAggs)
if err == nil {
for _, agg := range *denebAggs {
// TODO: Data version is not Deneb, it might be anything between Phase0 and Deneb
versionedAgg := eth2spec.VersionedSignedAggregateAndProof{
Version: eth2spec.DataVersionDeneb,
Deneb: &agg,
}
aggs = append(aggs, &versionedAgg)
}

return nil, nil, s.SubmitAggregateAttestations(ctx, &eth2api.SubmitAggregateAttestationsOpts{
SignedAggregateAndProofs: aggs,
})
}

err = s.SubmitAggregateAttestations(ctx, aggs)
if err != nil {
return nil, nil, err
electraAggs := new([]electra.SignedAggregateAndProof)
err = unmarshal(typ, body, electraAggs)
if err == nil {
for _, agg := range *electraAggs {
versionedAgg := eth2spec.VersionedSignedAggregateAndProof{
Version: eth2spec.DataVersionElectra,
Electra: &agg,
}
aggs = append(aggs, &versionedAgg)
}

Check warning on line 1062 in core/validatorapi/router.go

View check run for this annotation

Codecov / codecov/patch

core/validatorapi/router.go#L1053-L1062

Added lines #L1053 - L1062 were not covered by tests

return nil, nil, s.SubmitAggregateAttestations(ctx, &eth2api.SubmitAggregateAttestationsOpts{
SignedAggregateAndProofs: aggs,
})

Check warning on line 1066 in core/validatorapi/router.go

View check run for this annotation

Codecov / codecov/patch

core/validatorapi/router.go#L1064-L1066

Added lines #L1064 - L1066 were not covered by tests
}

return nil, nil, nil
return nil, nil, errors.New("invalid submitted aggregate and proofs", z.Hex("body", body))

Check warning on line 1069 in core/validatorapi/router.go

View check run for this annotation

Codecov / codecov/patch

core/validatorapi/router.go#L1069

Added line #L1069 was not covered by tests
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/validatorapi/validatorapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ func (c Component) SubmitAggregateAttestations(ctx context.Context, aggregateAnd
}
}

parSigData := core.NewPartialSignedAggregateAndProof(agg, c.shareIdx)
parSigData := core.NewPartialVersionedSignedAggregateAndProof(agg, c.shareIdx)

// Verify outer partial signature.
err = c.verifyPartialSig(ctx, parSigData, pk)
Expand Down
2 changes: 1 addition & 1 deletion core/validatorapi/validatorapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1696,7 +1696,7 @@ func TestComponent_SubmitAggregateAttestations(t *testing.T) {

data, ok := set[pk]
require.True(t, ok)
require.Equal(t, core.NewPartialSignedAggregateAndProof(agg, 0), data)
require.Equal(t, core.NewPartialVersionedSignedAggregateAndProof(agg, 0), data)

return nil
})
Expand Down
2 changes: 1 addition & 1 deletion testutil/beaconmock/beaconmock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func TestAttestationStore(t *testing.T) {
}
bmockResp, err := bmock.AggregateAttestation(ctx, aggAttOpts) // Slot is ignored.
require.NoError(t, err)
att := bmockResp.Data
att := bmockResp.Data.Deneb
require.Equal(t, attData, att.Data)

aggAttopts2 := &eth2api.AggregateAttestationOpts{
Expand Down
2 changes: 1 addition & 1 deletion testutil/beaconmock/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func newHTTPServer(addr string, optionalHandlers map[string]http.HandlerFunc, ov
"/eth/v1/validator/sync_committee_subscriptions": func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
},
"/eth/v1/validator/aggregate_attestation": func(w http.ResponseWriter, _ *http.Request) {
"/eth/v2/validator/aggregate_attestation": func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte(`{"code": 403,"message": "Beacon node was not assigned to aggregate on that subnet."}`))
},
Expand Down
16 changes: 16 additions & 0 deletions testutil/fuzz.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,5 +241,21 @@ func NewEth2Fuzzer(t *testing.T, seed int64) *fuzz.Fuzzer {
}
e.CommitteeBits = bits
},
func(e *core.VersionedAggregatedAttestation, c fuzz.Continue) {
e.Version = allVersions[(c.Intn(len(allVersions)))]
version, err := eth2util.DataVersionFromETH2(e.Version)
require.NoError(t, err)

val := core.VersionedSSZValueForT(t, e, version)
c.Fuzz(val)
},
func(e *core.VersionedSignedAggregateAndProof, c fuzz.Continue) {
e.Version = allVersions[(c.Intn(len(allVersions)))]
version, err := eth2util.DataVersionFromETH2(e.Version)
require.NoError(t, err)

val := core.VersionedSSZValueForT(t, e, version)
c.Fuzz(val)
},
)
}
Loading

0 comments on commit 461f76b

Please sign in to comment.