diff --git a/CHANGELOG.md b/CHANGELOG.md index f0f8dcc82b7e..82baea27ddf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,7 @@ Notable features: - Added more comprehensive tests for `BlockToLightClientHeader`. [PR](https://github.com/prysmaticlabs/prysm/pull/14699) - Added light client feature flag check to RPC handlers. [PR](https://github.com/prysmaticlabs/prysm/pull/14736) - Light client: Add better error handling. [PR](https://github.com/prysmaticlabs/prysm/pull/14749) +- Separate type for unaggregated network attestations. [PR](https://github.com/prysmaticlabs/prysm/pull/14659) ### Changed diff --git a/api/server/structs/conversions.go b/api/server/structs/conversions.go index 74af3c41aba5..780ebb50e3fa 100644 --- a/api/server/structs/conversions.go +++ b/api/server/structs/conversions.go @@ -432,6 +432,32 @@ func (a *AttestationElectra) ToConsensus() (*eth.AttestationElectra, error) { }, nil } +func (a *SingleAttestation) ToConsensus() (*eth.SingleAttestation, error) { + ci, err := strconv.ParseUint(a.CommitteeIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "CommitteeIndex") + } + ai, err := strconv.ParseUint(a.AttesterIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "AttesterIndex") + } + data, err := a.Data.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Data") + } + sig, err := bytesutil.DecodeHexWithLength(a.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + + return ð.SingleAttestation{ + CommitteeId: primitives.CommitteeIndex(ci), + AttesterIndex: primitives.ValidatorIndex(ai), + Data: data, + Signature: sig, + }, nil +} + func AttElectraFromConsensus(a *eth.AttestationElectra) *AttestationElectra { return &AttestationElectra{ AggregationBits: hexutil.Encode(a.AggregationBits), diff --git a/api/server/structs/other.go b/api/server/structs/other.go index e81789cb208c..ef5a00c56f90 100644 --- a/api/server/structs/other.go +++ b/api/server/structs/other.go @@ -36,6 +36,13 @@ type AttestationElectra struct { CommitteeBits string `json:"committee_bits"` } +type SingleAttestation struct { + CommitteeIndex string `json:"committee_index"` + AttesterIndex string `json:"attester_index"` + Data *AttestationData `json:"data"` + Signature string `json:"signature"` +} + type AttestationData struct { Slot string `json:"slot"` CommitteeIndex string `json:"index"` diff --git a/beacon-chain/core/helpers/attestation.go b/beacon-chain/core/helpers/attestation.go index 1c176a142955..ee234cc4c157 100644 --- a/beacon-chain/core/helpers/attestation.go +++ b/beacon-chain/core/helpers/attestation.go @@ -32,7 +32,7 @@ func ValidateNilAttestation(attestation ethpb.Att) error { if attestation.GetData().Target == nil { return errors.New("attestation's target can't be nil") } - if attestation.GetAggregationBits() == nil { + if !attestation.IsSingle() && attestation.GetAggregationBits() == nil { return errors.New("attestation's bitfield can't be nil") } return nil diff --git a/beacon-chain/core/helpers/attestation_test.go b/beacon-chain/core/helpers/attestation_test.go index 5459a6ac8b9a..e936abdddb40 100644 --- a/beacon-chain/core/helpers/attestation_test.go +++ b/beacon-chain/core/helpers/attestation_test.go @@ -308,6 +308,16 @@ func TestValidateNilAttestation(t *testing.T) { }, errString: "", }, + { + name: "single attestation", + attestation: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + Target: ðpb.Checkpoint{}, + Source: ðpb.Checkpoint{}, + }, + }, + errString: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/beacon-chain/core/helpers/beacon_committee_test.go b/beacon-chain/core/helpers/beacon_committee_test.go index 007685617e22..a9a95facc43c 100644 --- a/beacon-chain/core/helpers/beacon_committee_test.go +++ b/beacon-chain/core/helpers/beacon_committee_test.go @@ -97,6 +97,13 @@ func TestVerifyBitfieldLength_OK(t *testing.T) { assert.NoError(t, helpers.VerifyBitfieldLength(bf, committeeSize), "Bitfield is not validated when it was supposed to be") } +func TestVerifyBitfieldLength_Incorrect(t *testing.T) { + helpers.ClearCache() + + bf := bitfield.NewBitlist(1) + require.ErrorContains(t, "wanted participants bitfield length 2, got: 1", helpers.VerifyBitfieldLength(bf, 2)) +} + func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) { helpers.ClearCache() diff --git a/beacon-chain/p2p/gossip_topic_mappings.go b/beacon-chain/p2p/gossip_topic_mappings.go index d88a4499ce2b..819975006f17 100644 --- a/beacon-chain/p2p/gossip_topic_mappings.go +++ b/beacon-chain/p2p/gossip_topic_mappings.go @@ -47,7 +47,7 @@ func GossipTopicMappings(topic string, epoch primitives.Epoch) proto.Message { return gossipMessage(topic) case AttestationSubnetTopicFormat: if epoch >= params.BeaconConfig().ElectraForkEpoch { - return ðpb.AttestationElectra{} + return ðpb.SingleAttestation{} } return gossipMessage(topic) case AttesterSlashingSubnetTopicFormat: @@ -101,7 +101,7 @@ func init() { GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockDeneb{})] = BlockSubnetTopicFormat // Specially handle Electra objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockElectra{})] = BlockSubnetTopicFormat - GossipTypeMapping[reflect.TypeOf(ðpb.AttestationElectra{})] = AttestationSubnetTopicFormat + GossipTypeMapping[reflect.TypeOf(ðpb.SingleAttestation{})] = AttestationSubnetTopicFormat GossipTypeMapping[reflect.TypeOf(ðpb.AttesterSlashingElectra{})] = AttesterSlashingSubnetTopicFormat GossipTypeMapping[reflect.TypeOf(ðpb.SignedAggregateAttestationAndProofElectra{})] = AggregateAndProofSubnetTopicFormat } diff --git a/beacon-chain/p2p/gossip_topic_mappings_test.go b/beacon-chain/p2p/gossip_topic_mappings_test.go index 2c134f425fa6..acaa2f304f1b 100644 --- a/beacon-chain/p2p/gossip_topic_mappings_test.go +++ b/beacon-chain/p2p/gossip_topic_mappings_test.go @@ -118,7 +118,7 @@ func TestGossipTopicMappings_CorrectType(t *testing.T) { _, ok = pMessage.(*ethpb.SignedBeaconBlockElectra) assert.Equal(t, true, ok) pMessage = GossipTopicMappings(AttestationSubnetTopicFormat, electraForkEpoch) - _, ok = pMessage.(*ethpb.AttestationElectra) + _, ok = pMessage.(*ethpb.SingleAttestation) assert.Equal(t, true, ok) pMessage = GossipTopicMappings(AttesterSlashingSubnetTopicFormat, electraForkEpoch) _, ok = pMessage.(*ethpb.AttesterSlashingElectra) diff --git a/beacon-chain/p2p/types/object_mapping.go b/beacon-chain/p2p/types/object_mapping.go index e8646b34ee7a..b8ad6f155f25 100644 --- a/beacon-chain/p2p/types/object_mapping.go +++ b/beacon-chain/p2p/types/object_mapping.go @@ -112,7 +112,7 @@ func InitializeDataMaps() { return ðpb.Attestation{}, nil }, bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion): func() (ethpb.Att, error) { - return ðpb.AttestationElectra{}, nil + return ðpb.SingleAttestation{}, nil }, } diff --git a/beacon-chain/rpc/endpoints.go b/beacon-chain/rpc/endpoints.go index 14d5ad147329..97682b995fee 100644 --- a/beacon-chain/rpc/endpoints.go +++ b/beacon-chain/rpc/endpoints.go @@ -532,6 +532,7 @@ func (s *Service) beaconEndpoints( FinalizationFetcher: s.cfg.FinalizationFetcher, ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, CoreService: coreService, + AttestationStateFetcher: s.cfg.AttestationReceiver, } const namespace = "beacon" diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index 978913b49032..cf38095153a1 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -285,8 +285,11 @@ func (s *Server) SubmitAttestationsV2(w http.ResponseWriter, r *http.Request) { } } -func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMessage) (attFailures []*server.IndexedVerificationFailure, failedBroadcasts []string, err error) { - var sourceAttestations []*structs.AttestationElectra +func (s *Server) handleAttestationsElectra( + ctx context.Context, + data json.RawMessage, +) (attFailures []*server.IndexedVerificationFailure, failedBroadcasts []string, err error) { + var sourceAttestations []*structs.SingleAttestation if err = json.Unmarshal(data, &sourceAttestations); err != nil { return nil, nil, errors.Wrap(err, "failed to unmarshal attestation") @@ -296,7 +299,7 @@ func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMes return nil, nil, errors.New("no data submitted") } - var validAttestations []*eth.AttestationElectra + var validAttestations []*eth.SingleAttestation for i, sourceAtt := range sourceAttestations { att, err := sourceAtt.ToConsensus() if err != nil { @@ -317,6 +320,15 @@ func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMes } for i, att := range validAttestations { + targetState, err := s.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get target state for attestation") + } + committee, err := corehelpers.BeaconCommitteeFromState(ctx, targetState, att.Data.Slot, att.CommitteeId) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get committee for attestation") + } + // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node // of a received unaggregated attestation. // Note we can't send for aggregated att because we don't have selection proof. @@ -324,7 +336,7 @@ func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMes s.OperationNotifier.OperationFeed().Send(&feed.Event{ Type: operation.UnaggregatedAttReceived, Data: &operation.UnAggregatedAttReceivedData{ - Attestation: att, + Attestation: att.ToAttestationElectra(committee), }, }) } @@ -335,11 +347,7 @@ func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMes failedBroadcasts = append(failedBroadcasts, strconv.Itoa(i)) continue } - committeeIndex, err := att.GetCommitteeIndex() - if err != nil { - return nil, nil, errors.Wrap(err, "failed to retrieve attestation committee index") - } - subnet := corehelpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committeeIndex, att.Data.Slot) + subnet := corehelpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), att.GetCommitteeIndex(), att.Data.Slot) if err = s.Broadcaster.BroadcastAttestation(ctx, subnet, att); err != nil { log.WithError(err).Errorf("could not broadcast attestation at index %d", i) failedBroadcasts = append(failedBroadcasts, strconv.Itoa(i)) @@ -347,16 +355,12 @@ func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMes } if features.Get().EnableExperimentalAttestationPool { - if err = s.AttestationCache.Add(att); err != nil { + if err = s.AttestationCache.Add(att.ToAttestationElectra(committee)); err != nil { log.WithError(err).Error("could not save attestation") } - } else if att.IsAggregated() { - if err = s.AttestationsPool.SaveAggregatedAttestation(att); err != nil { - log.WithError(err).Error("could not save aggregated attestation") - } } else { - if err = s.AttestationsPool.SaveUnaggregatedAttestation(att); err != nil { - log.WithError(err).Error("could not save unaggregated attestation") + if err = s.AttestationsPool.SaveUnaggregatedAttestation(att.ToAttestationElectra(committee)); err != nil { + log.WithError(err).Error("could not save attestation") } } } diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool_test.go b/beacon-chain/rpc/eth/beacon/handlers_pool_test.go index 5ff2e5d228ae..6b44ea6fd6dc 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool_test.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool_test.go @@ -498,13 +498,17 @@ func TestSubmitAttestations(t *testing.T) { c.SlotsPerEpoch = 1 params.OverrideBeaconConfig(c) - _, keys, err := util.DeterministicDepositsAndKeys(1) + _, keys, err := util.DeterministicDepositsAndKeys(2) require.NoError(t, err) validators := []*ethpbv1alpha1.Validator{ { PublicKey: keys[0].PublicKey().Marshal(), ExitEpoch: params.BeaconConfig().FarFutureEpoch, }, + { + PublicKey: keys[1].PublicKey().Marshal(), + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + }, } bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { state.Validators = validators @@ -521,9 +525,10 @@ func TestSubmitAttestations(t *testing.T) { chainService := &blockchainmock.ChainService{State: bs} s := &Server{ - HeadFetcher: chainService, - ChainInfoFetcher: chainService, - OperationNotifier: &blockchainmock.MockOperationNotifier{}, + HeadFetcher: chainService, + ChainInfoFetcher: chainService, + OperationNotifier: &blockchainmock.MockOperationNotifier{}, + AttestationStateFetcher: chainService, } t.Run("V1", func(t *testing.T) { t.Run("single", func(t *testing.T) { @@ -732,7 +737,7 @@ func TestSubmitAttestations(t *testing.T) { assert.Equal(t, http.StatusOK, writer.Code) assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) assert.Equal(t, 1, broadcaster.NumAttestations()) - assert.Equal(t, "0x03", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetAggregationBits())) + assert.Equal(t, primitives.ValidatorIndex(1), broadcaster.BroadcastAttestations[0].GetAttestingIndex()) assert.Equal(t, "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetSignature())) assert.Equal(t, primitives.Slot(0), broadcaster.BroadcastAttestations[0].GetData().Slot) assert.Equal(t, primitives.CommitteeIndex(0), broadcaster.BroadcastAttestations[0].GetData().CommitteeIndex) @@ -2344,8 +2349,8 @@ var ( ]` singleAttElectra = `[ { - "aggregation_bits": "0x03", - "committee_bits": "0x0100000000000000", + "committee_index": "0", + "attester_index": "1", "signature": "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", "data": { "slot": "0", @@ -2364,8 +2369,8 @@ var ( ]` multipleAttsElectra = `[ { - "aggregation_bits": "0x03", - "committee_bits": "0x0100000000000000", + "committee_index": "0", + "attester_index": "0", "signature": "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", "data": { "slot": "0", @@ -2382,8 +2387,8 @@ var ( } }, { - "aggregation_bits": "0x03", - "committee_bits": "0x0100000000000000", + "committee_index": "0", + "attester_index": "1", "signature": "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", "data": { "slot": "0", @@ -2403,8 +2408,8 @@ var ( // signature is invalid invalidAttElectra = `[ { - "aggregation_bits": "0x03", - "committee_bits": "0x0100000000000000", + "committee_index": "0", + "attester_index": "0", "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "data": { "slot": "0", diff --git a/beacon-chain/rpc/eth/beacon/server.go b/beacon-chain/rpc/eth/beacon/server.go index f0af9e9f539c..4ac573288705 100644 --- a/beacon-chain/rpc/eth/beacon/server.go +++ b/beacon-chain/rpc/eth/beacon/server.go @@ -50,4 +50,5 @@ type Server struct { BLSChangesPool blstoexec.PoolManager ForkchoiceFetcher blockchain.ForkchoiceFetcher CoreService *core.Service + AttestationStateFetcher blockchain.AttestationStateFetcher } diff --git a/beacon-chain/rpc/eth/validator/handlers.go b/beacon-chain/rpc/eth/validator/handlers.go index 255b28deeb07..1a05167784ad 100644 --- a/beacon-chain/rpc/eth/validator/handlers.go +++ b/beacon-chain/rpc/eth/validator/handlers.go @@ -205,11 +205,7 @@ func matchingAtts(atts []ethpbalpha.Att, slot primitives.Slot, attDataRoot []byt // compare the committee index separately. if postElectra { if att.Version() >= version.Electra { - ci, err := att.GetCommitteeIndex() - if err != nil { - return nil, err - } - if ci != index { + if att.GetCommitteeIndex() != index { continue } } else { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go index cde312e8e197..857723a478f7 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -13,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -45,7 +46,7 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestation") defer span.End() - resp, err := vs.proposeAtt(ctx, att, att.GetData().CommitteeIndex) + resp, err := vs.proposeAtt(ctx, att, nil, att.GetData().CommitteeIndex) if err != nil { return nil, err } @@ -69,29 +70,34 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation // ProposeAttestationElectra is a function called by an attester to vote // on a block via an attestation object as defined in the Ethereum specification. -func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) { +func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestationElectra") defer span.End() - committeeIndex, err := att.GetCommitteeIndex() + targetState, err := vs.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target) if err != nil { - return nil, err + return nil, status.Error(codes.Internal, "Could not get target state") + } + committeeIndex := att.GetCommitteeIndex() + committee, err := helpers.BeaconCommitteeFromState(ctx, targetState, att.Data.Slot, committeeIndex) + if err != nil { + return nil, status.Error(codes.Internal, "Could not get committee") } - resp, err := vs.proposeAtt(ctx, att, committeeIndex) + resp, err := vs.proposeAtt(ctx, att, committee, committeeIndex) if err != nil { return nil, err } if features.Get().EnableExperimentalAttestationPool { - if err = vs.AttestationCache.Add(att); err != nil { + if err = vs.AttestationCache.Add(att.ToAttestationElectra(committee)); err != nil { log.WithError(err).Error("Could not save attestation") } } else { go func() { ctx = trace.NewContext(context.Background(), trace.FromContext(ctx)) attCopy := att.Copy() - if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil { + if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy.ToAttestationElectra(committee)); err != nil { log.WithError(err).Error("Could not save unaggregated attestation") return } @@ -149,14 +155,29 @@ func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.Comm return &emptypb.Empty{}, nil } -func (vs *Server) proposeAtt(ctx context.Context, att ethpb.Att, committee primitives.CommitteeIndex) (*ethpb.AttestResponse, error) { +func (vs *Server) proposeAtt( + ctx context.Context, + att ethpb.Att, + committee []primitives.ValidatorIndex, // required post-Electra + committeeIndex primitives.CommitteeIndex, +) (*ethpb.AttestResponse, error) { if _, err := bls.SignatureFromBytes(att.GetSignature()); err != nil { return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature") } root, err := att.GetData().HashTreeRoot() if err != nil { - return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err) + return nil, status.Errorf(codes.Internal, "Could not get attestation root: %v", err) + } + + var singleAtt *ethpb.SingleAttestation + if att.Version() >= version.Electra { + var ok bool + singleAtt, ok = att.(*ethpb.SingleAttestation) + if !ok { + return nil, status.Errorf(codes.Internal, "Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, att) + } + att = singleAtt.ToAttestationElectra(committee) } // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node @@ -174,10 +195,16 @@ func (vs *Server) proposeAtt(ctx context.Context, att ethpb.Att, committee primi if err != nil { return nil, err } - subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committee, att.GetData().Slot) + subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committeeIndex, att.GetData().Slot) // Broadcast the new attestation to the network. - if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil { + var attToBroadcast ethpb.Att + if singleAtt != nil { + attToBroadcast = singleAtt + } else { + attToBroadcast = att + } + if err := vs.P2P.BroadcastAttestation(ctx, subnet, attToBroadcast); err != nil { return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go index 556afed89f20..6a5bab8c9bb4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go @@ -31,11 +31,13 @@ import ( ) func TestProposeAttestation(t *testing.T) { + chainService := &mock.ChainService{} attesterServer := &Server{ - HeadFetcher: &mock.ChainService{}, - P2P: &mockp2p.MockBroadcaster{}, - AttPool: attestations.NewPool(), - OperationNotifier: (&mock.ChainService{}).OperationNotifier(), + HeadFetcher: chainService, + P2P: &mockp2p.MockBroadcaster{}, + AttPool: attestations.NewPool(), + OperationNotifier: (&mock.ChainService{}).OperationNotifier(), + AttestationStateFetcher: chainService, } head := util.NewBeaconBlock() head.Block.Slot = 999 @@ -79,81 +81,19 @@ func TestProposeAttestation(t *testing.T) { require.NoError(t, err) require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) require.NoError(t, state.SetValidators(validators)) + chainService.State = state - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - req := ðpb.AttestationElectra{ + req := ðpb.SingleAttestation{ Signature: sig.Marshal(), Data: ðpb.AttestationData{ BeaconBlockRoot: root[:], Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}, }, - CommitteeBits: cb, } _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) assert.NoError(t, err) }) - t.Run("Electra - non-zero committee index", func(t *testing.T) { - state, err := util.NewBeaconStateElectra() - require.NoError(t, err) - require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) - require.NoError(t, state.SetValidators(validators)) - - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - req := ðpb.AttestationElectra{ - Signature: sig.Marshal(), - Data: ðpb.AttestationData{ - BeaconBlockRoot: root[:], - Source: ðpb.Checkpoint{Root: make([]byte, 32)}, - Target: ðpb.Checkpoint{Root: make([]byte, 32)}, - CommitteeIndex: 1, - }, - CommitteeBits: cb, - } - _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) - assert.ErrorContains(t, "attestation data's committee index must be 0 but was 1", err) - }) - t.Run("Electra - no committee bit set", func(t *testing.T) { - state, err := util.NewBeaconStateElectra() - require.NoError(t, err) - require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) - require.NoError(t, state.SetValidators(validators)) - - req := ðpb.AttestationElectra{ - Signature: sig.Marshal(), - Data: ðpb.AttestationData{ - BeaconBlockRoot: root[:], - Source: ðpb.Checkpoint{Root: make([]byte, 32)}, - Target: ðpb.Checkpoint{Root: make([]byte, 32)}, - }, - CommitteeBits: primitives.NewAttestationCommitteeBits(), - } - _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) - assert.ErrorContains(t, "exactly 1 committee index must be set but 0 were set", err) - }) - t.Run("Electra - multiple committee bits set", func(t *testing.T) { - state, err := util.NewBeaconStateElectra() - require.NoError(t, err) - require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) - require.NoError(t, state.SetValidators(validators)) - - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - cb.SetBitAt(1, true) - req := ðpb.AttestationElectra{ - Signature: sig.Marshal(), - Data: ðpb.AttestationData{ - BeaconBlockRoot: root[:], - Source: ðpb.Checkpoint{Root: make([]byte, 32)}, - Target: ðpb.Checkpoint{Root: make([]byte, 32)}, - }, - CommitteeBits: cb, - } - _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) - assert.ErrorContains(t, "exactly 1 committee index must be set but 2 were set", err) - }) } func TestProposeAttestation_IncorrectSignature(t *testing.T) { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go index 559adcc026b5..d125abfbd694 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go @@ -42,43 +42,44 @@ import ( // and committees in which particular validators need to perform their responsibilities, // and more. type Server struct { - Ctx context.Context - PayloadIDCache *cache.PayloadIDCache - TrackedValidatorsCache *cache.TrackedValidatorsCache - HeadFetcher blockchain.HeadFetcher - ForkFetcher blockchain.ForkFetcher - ForkchoiceFetcher blockchain.ForkchoiceFetcher - GenesisFetcher blockchain.GenesisFetcher - FinalizationFetcher blockchain.FinalizationFetcher - TimeFetcher blockchain.TimeFetcher - BlockFetcher execution.POWBlockFetcher - DepositFetcher cache.DepositFetcher - ChainStartFetcher execution.ChainStartFetcher - Eth1InfoFetcher execution.ChainInfoFetcher - OptimisticModeFetcher blockchain.OptimisticModeFetcher - SyncChecker sync.Checker - StateNotifier statefeed.Notifier - BlockNotifier blockfeed.Notifier - P2P p2p.Broadcaster - AttestationCache *cache.AttestationCache - AttPool attestations.Pool - SlashingsPool slashings.PoolManager - ExitPool voluntaryexits.PoolManager - SyncCommitteePool synccommittee.Pool - BlockReceiver blockchain.BlockReceiver - BlobReceiver blockchain.BlobReceiver - MockEth1Votes bool - Eth1BlockFetcher execution.POWBlockFetcher - PendingDepositsFetcher depositsnapshot.PendingDepositsFetcher - OperationNotifier opfeed.Notifier - StateGen stategen.StateManager - ReplayerBuilder stategen.ReplayerBuilder - BeaconDB db.HeadAccessDatabase - ExecutionEngineCaller execution.EngineCaller - BlockBuilder builder.BlockBuilder - BLSChangesPool blstoexec.PoolManager - ClockWaiter startup.ClockWaiter - CoreService *core.Service + Ctx context.Context + PayloadIDCache *cache.PayloadIDCache + TrackedValidatorsCache *cache.TrackedValidatorsCache + HeadFetcher blockchain.HeadFetcher + ForkFetcher blockchain.ForkFetcher + ForkchoiceFetcher blockchain.ForkchoiceFetcher + GenesisFetcher blockchain.GenesisFetcher + FinalizationFetcher blockchain.FinalizationFetcher + TimeFetcher blockchain.TimeFetcher + BlockFetcher execution.POWBlockFetcher + DepositFetcher cache.DepositFetcher + ChainStartFetcher execution.ChainStartFetcher + Eth1InfoFetcher execution.ChainInfoFetcher + OptimisticModeFetcher blockchain.OptimisticModeFetcher + SyncChecker sync.Checker + StateNotifier statefeed.Notifier + BlockNotifier blockfeed.Notifier + P2P p2p.Broadcaster + AttestationCache *cache.AttestationCache + AttPool attestations.Pool + SlashingsPool slashings.PoolManager + ExitPool voluntaryexits.PoolManager + SyncCommitteePool synccommittee.Pool + BlockReceiver blockchain.BlockReceiver + BlobReceiver blockchain.BlobReceiver + MockEth1Votes bool + Eth1BlockFetcher execution.POWBlockFetcher + PendingDepositsFetcher depositsnapshot.PendingDepositsFetcher + OperationNotifier opfeed.Notifier + StateGen stategen.StateManager + ReplayerBuilder stategen.ReplayerBuilder + BeaconDB db.HeadAccessDatabase + ExecutionEngineCaller execution.EngineCaller + BlockBuilder builder.BlockBuilder + BLSChangesPool blstoexec.PoolManager + ClockWaiter startup.ClockWaiter + CoreService *core.Service + AttestationStateFetcher blockchain.AttestationStateFetcher } // WaitForActivation checks if a validator public key exists in the active validator registry of the current diff --git a/beacon-chain/rpc/service.go b/beacon-chain/rpc/service.go index 24212eddff1b..08585a2201bb 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -212,43 +212,44 @@ func NewService(ctx context.Context, cfg *Config) *Service { OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, } validatorServer := &validatorv1alpha1.Server{ - Ctx: s.ctx, - AttestationCache: s.cfg.AttestationCache, - AttPool: s.cfg.AttestationsPool, - ExitPool: s.cfg.ExitPool, - HeadFetcher: s.cfg.HeadFetcher, - ForkFetcher: s.cfg.ForkFetcher, - ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, - GenesisFetcher: s.cfg.GenesisFetcher, - FinalizationFetcher: s.cfg.FinalizationFetcher, - TimeFetcher: s.cfg.GenesisTimeFetcher, - BlockFetcher: s.cfg.ExecutionChainService, - DepositFetcher: s.cfg.DepositFetcher, - ChainStartFetcher: s.cfg.ChainStartFetcher, - Eth1InfoFetcher: s.cfg.ExecutionChainService, - OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, - SyncChecker: s.cfg.SyncService, - StateNotifier: s.cfg.StateNotifier, - BlockNotifier: s.cfg.BlockNotifier, - OperationNotifier: s.cfg.OperationNotifier, - P2P: s.cfg.Broadcaster, - BlockReceiver: s.cfg.BlockReceiver, - BlobReceiver: s.cfg.BlobReceiver, - MockEth1Votes: s.cfg.MockEth1Votes, - Eth1BlockFetcher: s.cfg.ExecutionChainService, - PendingDepositsFetcher: s.cfg.PendingDepositFetcher, - SlashingsPool: s.cfg.SlashingsPool, - StateGen: s.cfg.StateGen, - SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, - ReplayerBuilder: ch, - ExecutionEngineCaller: s.cfg.ExecutionEngineCaller, - BeaconDB: s.cfg.BeaconDB, - BlockBuilder: s.cfg.BlockBuilder, - BLSChangesPool: s.cfg.BLSChangesPool, - ClockWaiter: s.cfg.ClockWaiter, - CoreService: coreService, - TrackedValidatorsCache: s.cfg.TrackedValidatorsCache, - PayloadIDCache: s.cfg.PayloadIDCache, + Ctx: s.ctx, + AttestationCache: s.cfg.AttestationCache, + AttPool: s.cfg.AttestationsPool, + ExitPool: s.cfg.ExitPool, + HeadFetcher: s.cfg.HeadFetcher, + ForkFetcher: s.cfg.ForkFetcher, + ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, + GenesisFetcher: s.cfg.GenesisFetcher, + FinalizationFetcher: s.cfg.FinalizationFetcher, + TimeFetcher: s.cfg.GenesisTimeFetcher, + BlockFetcher: s.cfg.ExecutionChainService, + DepositFetcher: s.cfg.DepositFetcher, + ChainStartFetcher: s.cfg.ChainStartFetcher, + Eth1InfoFetcher: s.cfg.ExecutionChainService, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, + SyncChecker: s.cfg.SyncService, + StateNotifier: s.cfg.StateNotifier, + BlockNotifier: s.cfg.BlockNotifier, + OperationNotifier: s.cfg.OperationNotifier, + P2P: s.cfg.Broadcaster, + BlockReceiver: s.cfg.BlockReceiver, + BlobReceiver: s.cfg.BlobReceiver, + MockEth1Votes: s.cfg.MockEth1Votes, + Eth1BlockFetcher: s.cfg.ExecutionChainService, + PendingDepositsFetcher: s.cfg.PendingDepositFetcher, + SlashingsPool: s.cfg.SlashingsPool, + StateGen: s.cfg.StateGen, + SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, + ReplayerBuilder: ch, + ExecutionEngineCaller: s.cfg.ExecutionEngineCaller, + BeaconDB: s.cfg.BeaconDB, + BlockBuilder: s.cfg.BlockBuilder, + BLSChangesPool: s.cfg.BLSChangesPool, + ClockWaiter: s.cfg.ClockWaiter, + CoreService: coreService, + TrackedValidatorsCache: s.cfg.TrackedValidatorsCache, + PayloadIDCache: s.cfg.PayloadIDCache, + AttestationStateFetcher: s.cfg.AttestationReceiver, } s.validatorServer = validatorServer nodeServer := &nodev1alpha1.Server{ diff --git a/beacon-chain/sync/BUILD.bazel b/beacon-chain/sync/BUILD.bazel index d402887db6bb..5325f5c0ea1a 100644 --- a/beacon-chain/sync/BUILD.bazel +++ b/beacon-chain/sync/BUILD.bazel @@ -44,7 +44,6 @@ go_library( "validate_aggregate_proof.go", "validate_attester_slashing.go", "validate_beacon_attestation.go", - "validate_beacon_attestation_electra.go", "validate_beacon_blocks.go", "validate_blob.go", "validate_bls_to_execution_change.go", @@ -179,7 +178,6 @@ go_test( "sync_test.go", "validate_aggregate_proof_test.go", "validate_attester_slashing_test.go", - "validate_beacon_attestation_electra_test.go", "validate_beacon_attestation_test.go", "validate_beacon_blocks_test.go", "validate_blob_test.go", diff --git a/beacon-chain/sync/decode_pubsub_test.go b/beacon-chain/sync/decode_pubsub_test.go index 1ae8f0dd6ede..0a7aa581baf1 100644 --- a/beacon-chain/sync/decode_pubsub_test.go +++ b/beacon-chain/sync/decode_pubsub_test.go @@ -274,7 +274,7 @@ func TestExtractDataType(t *testing.T) { return wsb }(), wantMd: wrapper.WrappedMetadataV1(ðpb.MetaDataV1{}), - wantAtt: ðpb.AttestationElectra{}, + wantAtt: ðpb.SingleAttestation{}, wantAggregate: ðpb.SignedAggregateAttestationAndProofElectra{}, wantErr: false, }, diff --git a/beacon-chain/sync/pending_attestations_queue.go b/beacon-chain/sync/pending_attestations_queue.go index 4201737af5e6..7fc849b5fabe 100644 --- a/beacon-chain/sync/pending_attestations_queue.go +++ b/beacon-chain/sync/pending_attestations_queue.go @@ -91,86 +91,118 @@ func (s *Service) processPendingAtts(ctx context.Context) error { func (s *Service) processAttestations(ctx context.Context, attestations []ethpb.SignedAggregateAttAndProof) { for _, signedAtt := range attestations { - aggregate := signedAtt.AggregateAttestationAndProof().AggregateVal() - data := aggregate.GetData() + att := signedAtt.AggregateAttestationAndProof().AggregateVal() // The pending attestations can arrive in both aggregated and unaggregated forms, // each from has distinct validation steps. - if aggregate.IsAggregated() { - // Save the pending aggregated attestation to the pool if it passes the aggregated - // validation steps. - valRes, err := s.validateAggregatedAtt(ctx, signedAtt) - if err != nil { - log.WithError(err).Debug("Pending aggregated attestation failed validation") - } - aggValid := pubsub.ValidationAccept == valRes - if s.validateBlockInAttestation(ctx, signedAtt) && aggValid { - if features.Get().EnableExperimentalAttestationPool { - if err = s.cfg.attestationCache.Add(aggregate); err != nil { - log.WithError(err).Debug("Could not save aggregate attestation") - continue - } - } else { - if err := s.cfg.attPool.SaveAggregatedAttestation(aggregate); err != nil { - log.WithError(err).Debug("Could not save aggregate attestation") - continue - } - } + if att.IsAggregated() { + s.processAggregated(ctx, signedAtt) + } else { + s.processUnaggregated(ctx, att) + } + } +} - s.setAggregatorIndexEpochSeen(data.Target.Epoch, signedAtt.AggregateAttestationAndProof().GetAggregatorIndex()) +func (s *Service) processAggregated(ctx context.Context, att ethpb.SignedAggregateAttAndProof) { + aggregate := att.AggregateAttestationAndProof().AggregateVal() - // Broadcasting the signed attestation again once a node is able to process it. - if err := s.cfg.p2p.Broadcast(ctx, signedAtt); err != nil { - log.WithError(err).Debug("Could not broadcast") - } + // Save the pending aggregated attestation to the pool if it passes the aggregated + // validation steps. + valRes, err := s.validateAggregatedAtt(ctx, att) + if err != nil { + log.WithError(err).Debug("Pending aggregated attestation failed validation") + } + aggValid := pubsub.ValidationAccept == valRes + if s.validateBlockInAttestation(ctx, att) && aggValid { + if features.Get().EnableExperimentalAttestationPool { + if err = s.cfg.attestationCache.Add(aggregate); err != nil { + log.WithError(err).Debug("Could not save aggregate attestation") + return } } else { - // This is an important validation before retrieving attestation pre state to defend against - // attestation's target intentionally reference checkpoint that's long ago. - // Verify current finalized checkpoint is an ancestor of the block defined by the attestation's beacon block root. - if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { - log.WithError(blockchain.ErrNotDescendantOfFinalized).Debug("Could not verify finalized consistency") - continue - } - if err := s.cfg.chain.VerifyLmdFfgConsistency(ctx, aggregate); err != nil { - log.WithError(err).Debug("Could not verify FFG consistency") - continue - } - preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) - if err != nil { - log.WithError(err).Debug("Could not retrieve attestation prestate") - continue + if err := s.cfg.attPool.SaveAggregatedAttestation(aggregate); err != nil { + log.WithError(err).Debug("Could not save aggregate attestation") + return } + } - valid, err := s.validateUnaggregatedAttWithState(ctx, aggregate, preState) - if err != nil { - log.WithError(err).Debug("Pending unaggregated attestation failed validation") - continue - } - if valid == pubsub.ValidationAccept { - if features.Get().EnableExperimentalAttestationPool { - if err = s.cfg.attestationCache.Add(aggregate); err != nil { - log.WithError(err).Debug("Could not save unaggregated attestation") - continue - } - } else { - if err := s.cfg.attPool.SaveUnaggregatedAttestation(aggregate); err != nil { - log.WithError(err).Debug("Could not save unaggregated attestation") - continue - } - } - s.setSeenCommitteeIndicesSlot(data.Slot, data.CommitteeIndex, aggregate.GetAggregationBits()) + s.setAggregatorIndexEpochSeen(aggregate.GetData().Target.Epoch, att.AggregateAttestationAndProof().GetAggregatorIndex()) - valCount, err := helpers.ActiveValidatorCount(ctx, preState, slots.ToEpoch(data.Slot)) - if err != nil { - log.WithError(err).Debug("Could not retrieve active validator count") - continue - } - // Broadcasting the signed attestation again once a node is able to process it. - if err := s.cfg.p2p.BroadcastAttestation(ctx, helpers.ComputeSubnetForAttestation(valCount, aggregate), aggregate); err != nil { - log.WithError(err).Debug("Could not broadcast") - } + // Broadcasting the signed attestation again once a node is able to process it. + if err := s.cfg.p2p.Broadcast(ctx, att); err != nil { + log.WithError(err).Debug("Could not broadcast") + } + } +} + +func (s *Service) processUnaggregated(ctx context.Context, att ethpb.Att) { + data := att.GetData() + + // This is an important validation before retrieving attestation pre state to defend against + // attestation's target intentionally reference checkpoint that's long ago. + // Verify current finalized checkpoint is an ancestor of the block defined by the attestation's beacon block root. + if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { + log.WithError(blockchain.ErrNotDescendantOfFinalized).Debug("Could not verify finalized consistency") + return + } + if err := s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { + log.WithError(err).Debug("Could not verify FFG consistency") + return + } + preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) + if err != nil { + log.WithError(err).Debug("Could not retrieve attestation prestate") + return + } + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, data.Slot, att.GetCommitteeIndex()) + if err != nil { + log.WithError(err).Debug("Could not retrieve committee from state") + return + } + valid, err := validateAttesterData(ctx, att, committee) + if err != nil { + log.WithError(err).Debug("Could not validate attester data") + return + } else if valid != pubsub.ValidationAccept { + log.Debug("Attestation failed attester data validation") + return + } + if att.Version() >= version.Electra { + var ok bool + singleAtt, ok := att.(*ethpb.SingleAttestation) + if !ok { + log.Debugf("Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, att) + return + } + att = singleAtt.ToAttestationElectra(committee) + } + valid, err = s.validateUnaggregatedAttWithState(ctx, att, preState) + if err != nil { + log.WithError(err).Debug("Pending unaggregated attestation failed validation") + return + } + if valid == pubsub.ValidationAccept { + if features.Get().EnableExperimentalAttestationPool { + if err = s.cfg.attestationCache.Add(att); err != nil { + log.WithError(err).Debug("Could not save unaggregated attestation") + return + } + } else { + if err := s.cfg.attPool.SaveUnaggregatedAttestation(att); err != nil { + log.WithError(err).Debug("Could not save unaggregated attestation") + return } } + s.setSeenCommitteeIndicesSlot(data.Slot, data.CommitteeIndex, att.GetAggregationBits()) + + valCount, err := helpers.ActiveValidatorCount(ctx, preState, slots.ToEpoch(data.Slot)) + if err != nil { + log.WithError(err).Debug("Could not retrieve active validator count") + return + } + // Broadcasting the signed attestation again once a node is able to process it. + if err := s.cfg.p2p.BroadcastAttestation(ctx, helpers.ComputeSubnetForAttestation(valCount, att), att); err != nil { + log.WithError(err).Debug("Could not broadcast") + } } } diff --git a/beacon-chain/sync/pending_attestations_queue_test.go b/beacon-chain/sync/pending_attestations_queue_test.go index cccdefa1fbc0..702cff394742 100644 --- a/beacon-chain/sync/pending_attestations_queue_test.go +++ b/beacon-chain/sync/pending_attestations_queue_test.go @@ -92,18 +92,9 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) { att.Signature = privKeys[i].Sign(hashTreeRoot[:]).Marshal() } - // Arbitrary aggregator index for testing purposes. - aggregatorIndex := committee[0] - sszUint := primitives.SSZUint64(att.Data.Slot) - sig, err := signing.ComputeDomainAndSign(beaconState, 0, &sszUint, params.BeaconConfig().DomainSelectionProof, privKeys[aggregatorIndex]) - require.NoError(t, err) aggregateAndProof := ðpb.AggregateAttestationAndProof{ - SelectionProof: sig, - Aggregate: att, - AggregatorIndex: aggregatorIndex, + Aggregate: att, } - aggreSig, err := signing.ComputeDomainAndSign(beaconState, 0, aggregateAndProof, params.BeaconConfig().DomainAggregateAndProof, privKeys[aggregatorIndex]) - require.NoError(t, err) require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix()))) @@ -134,7 +125,7 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) { require.NoError(t, err) require.NoError(t, r.cfg.beaconDB.SaveState(context.Background(), s, root)) - r.blkRootToPendingAtts[root] = []ethpb.SignedAggregateAttAndProof{ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof, Signature: aggreSig}} + r.blkRootToPendingAtts[root] = []ethpb.SignedAggregateAttAndProof{ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}} require.NoError(t, r.processPendingAtts(context.Background())) atts, err := r.cfg.attPool.UnaggregatedAttestations() @@ -146,6 +137,80 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) { cancel() } +func TestProcessPendingAtts_HasBlockSaveUnAggregatedAttElectra(t *testing.T) { + hook := logTest.NewGlobal() + db := dbtest.SetupDB(t) + p1 := p2ptest.NewTestP2P(t) + validators := uint64(256) + + beaconState, privKeys := util.DeterministicGenesisStateElectra(t, validators) + + sb := util.NewBeaconBlockElectra() + util.SaveBlock(t, context.Background(), db, sb) + root, err := sb.Block.HashTreeRoot() + require.NoError(t, err) + + att := ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: root[:], + Source: ðpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)}, + Target: ðpb.Checkpoint{Epoch: 0, Root: root[:]}, + }, + } + aggregateAndProof := ðpb.AggregateAttestationAndProofSingle{ + Aggregate: att, + } + + committee, err := helpers.BeaconCommitteeFromState(context.Background(), beaconState, att.Data.Slot, att.Data.CommitteeIndex) + assert.NoError(t, err) + att.AttesterIndex = committee[0] + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot()) + require.NoError(t, err) + hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) + assert.NoError(t, err) + att.Signature = privKeys[committee[0]].Sign(hashTreeRoot[:]).Marshal() + + require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix()))) + + chain := &mock.ChainService{Genesis: time.Now(), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Root: aggregateAndProof.Aggregate.Data.BeaconBlockRoot, + Epoch: 0, + }, + } + ctx, cancel := context.WithCancel(context.Background()) + r := &Service{ + ctx: ctx, + cfg: &config{ + p2p: p1, + beaconDB: db, + chain: chain, + clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), + attPool: attestations.NewPool(), + }, + blkRootToPendingAtts: make(map[[32]byte][]ethpb.SignedAggregateAttAndProof), + seenUnAggregatedAttestationCache: lruwrpr.New(10), + signatureChan: make(chan *signatureVerifier, verifierLimit), + } + go r.verifierRoutine() + + s, err := util.NewBeaconStateElectra() + require.NoError(t, err) + require.NoError(t, r.cfg.beaconDB.SaveState(context.Background(), s, root)) + + r.blkRootToPendingAtts[root] = []ethpb.SignedAggregateAttAndProof{ðpb.SignedAggregateAttestationAndProofSingle{Message: aggregateAndProof}} + require.NoError(t, r.processPendingAtts(context.Background())) + + atts, err := r.cfg.attPool.UnaggregatedAttestations() + require.NoError(t, err) + require.Equal(t, 1, len(atts), "Did not save unaggregated att") + assert.DeepEqual(t, att.ToAttestationElectra(committee), atts[0], "Incorrect saved att") + assert.Equal(t, 0, len(r.cfg.attPool.AggregatedAttestations()), "Did save aggregated att") + require.LogsContain(t, hook, "Verified and saved pending attestations to pool") + cancel() +} + func TestProcessPendingAtts_NoBroadcastWithBadSignature(t *testing.T) { db := dbtest.SetupDB(t) p1 := p2ptest.NewTestP2P(t) diff --git a/beacon-chain/sync/subscriber_beacon_attestation.go b/beacon-chain/sync/subscriber_beacon_attestation.go index 15142c6d1baf..37c4c7972429 100644 --- a/beacon-chain/sync/subscriber_beacon_attestation.go +++ b/beacon-chain/sync/subscriber_beacon_attestation.go @@ -26,10 +26,7 @@ func (s *Service) committeeIndexBeaconAttestationSubscriber(_ context.Context, m if data == nil { return errors.New("nil attestation") } - committeeIndex, err := a.GetCommitteeIndex() - if err != nil { - return errors.Wrap(err, "committeeIndexBeaconAttestationSubscriber failed to get committee index") - } + committeeIndex := a.GetCommitteeIndex() s.setSeenCommitteeIndicesSlot(data.Slot, committeeIndex, a.GetAggregationBits()) if features.Get().EnableExperimentalAttestationPool { diff --git a/beacon-chain/sync/validate_aggregate_proof.go b/beacon-chain/sync/validate_aggregate_proof.go index e3a61d02e86c..a9546967a65b 100644 --- a/beacon-chain/sync/validate_aggregate_proof.go +++ b/beacon-chain/sync/validate_aggregate_proof.go @@ -183,16 +183,23 @@ func (s *Service) validateAggregatedAtt(ctx context.Context, signed ethpb.Signed return pubsub.ValidationIgnore, err } - committeeIndex, _, result, err := s.validateCommitteeIndexAndCount(ctx, aggregate, bs) + committeeIndex, _, result, err := s.validateCommitteeIndex(ctx, aggregate, bs) if result != pubsub.ValidationAccept { wrappedErr := errors.Wrapf(err, "could not validate committee index") tracing.AnnotateError(span, wrappedErr) return result, err } - committee, result, err := s.validateBitLength(ctx, bs, aggregate.GetData().Slot, committeeIndex, aggregate.GetAggregationBits()) - if result != pubsub.ValidationAccept { - return result, err + committee, err := helpers.BeaconCommitteeFromState(ctx, bs, aggregate.GetData().Slot, committeeIndex) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + + // Verify number of aggregation bits matches the committee size. + if err = helpers.VerifyBitfieldLength(aggregate.GetAggregationBits(), uint64(len(committee))); err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationReject, err } // Verify validator index is within the beacon committee. diff --git a/beacon-chain/sync/validate_aggregate_proof_test.go b/beacon-chain/sync/validate_aggregate_proof_test.go index 6376e3f42d6e..e07366a273e8 100644 --- a/beacon-chain/sync/validate_aggregate_proof_test.go +++ b/beacon-chain/sync/validate_aggregate_proof_test.go @@ -94,15 +94,8 @@ func TestVerifyIndexInCommittee_ExistsInBeaconCommittee(t *testing.T) { assert.ErrorContains(t, wanted, err) assert.Equal(t, pubsub.ValidationReject, result) - att.AggregationBits = bitfield.NewBitlist(1) - committeeIndex, err := att.GetCommitteeIndex() - require.NoError(t, err) - _, result, err = service.validateBitLength(ctx, s, att.Data.Slot, committeeIndex, att.AggregationBits) - require.ErrorContains(t, "wanted participants bitfield length 4, got: 1", err) - assert.Equal(t, pubsub.ValidationReject, result) - att.Data.CommitteeIndex = 10000 - _, _, result, err = service.validateCommitteeIndexAndCount(ctx, att, s) + _, _, result, err = service.validateCommitteeIndex(ctx, att, s) require.ErrorContains(t, "committee index 10000 > 2", err) assert.Equal(t, pubsub.ValidationReject, result) } diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 11c842e484bf..f7dc4c6c4fcf 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -9,7 +9,6 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/peer" "github.com/pkg/errors" - "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" @@ -71,14 +70,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p if data.Slot == 0 { return pubsub.ValidationIgnore, nil } - // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node - // of a received unaggregated attestation. - s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ - Type: operation.UnaggregatedAttReceived, - Data: &operation.UnAggregatedAttReceivedData{ - Attestation: att, - }, - }) // Attestation's slot is within ATTESTATION_PROPAGATION_SLOT_RANGE and early attestation // processing tolerance. @@ -91,14 +82,7 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationReject, err } - var validationRes pubsub.ValidationResult - - committeeIndex, result, err := s.validateCommitteeIndex(ctx, att) - if result != pubsub.ValidationAccept { - wrappedErr := errors.Wrapf(err, "could not validate committee index for %s version", version.String(att.Version())) - tracing.AnnotateError(span, wrappedErr) - return result, wrappedErr - } + committeeIndex := att.GetCommitteeIndex() if !features.Get().EnableSlasher { // Verify this the first attestation received for the participating validator for the slot. @@ -115,17 +99,19 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p } } + var validationRes pubsub.ValidationResult + // Verify the block being voted and the processed state is in beaconDB and the block has passed validation if it's in the beaconDB. blockRoot := bytesutil.ToBytes32(data.BeaconBlockRoot) if !s.hasBlockAndState(ctx, blockRoot) { // A node doesn't have the block, it'll request from peer while saving the pending attestation to a queue. if att.Version() >= version.Electra { - a, ok := att.(*eth.AttestationElectra) + a, ok := att.(*eth.SingleAttestation) // This will never fail in practice because we asserted the version if !ok { - return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.AttestationElectra{}, att) + return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, att) } - s.savePendingAtt(ð.SignedAggregateAttestationAndProofElectra{Message: ð.AggregateAttestationAndProofElectra{Aggregate: a}}) + s.savePendingAtt(ð.SignedAggregateAttestationAndProofSingle{Message: ð.AggregateAttestationAndProofSingle{Aggregate: a}}) } else { a, ok := att.(*eth.Attestation) // This will never fail in practice because we asserted the version @@ -141,7 +127,7 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p tracing.AnnotateError(span, blockchain.ErrNotDescendantOfFinalized) return pubsub.ValidationIgnore, blockchain.ErrNotDescendantOfFinalized } - if err := s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { + if err = s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { tracing.AnnotateError(span, err) attBadLmdConsistencyCount.Inc() return pubsub.ValidationReject, err @@ -158,6 +144,25 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return validationRes, err } + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + + validationRes, err = validateAttesterData(ctx, att, committee) + if validationRes != pubsub.ValidationAccept { + return validationRes, err + } + + if att.Version() >= version.Electra { + singleAtt, ok := att.(*eth.SingleAttestation) + if !ok { + return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, att) + } + att = singleAtt.ToAttestationElectra(committee) + } + validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, preState) if validationRes != pubsub.ValidationAccept { return validationRes, err @@ -192,6 +197,15 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p }() } + // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node + // of a received unaggregated attestation. + s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.UnaggregatedAttReceived, + Data: &operation.UnAggregatedAttReceivedData{ + Attestation: att, + }, + }) + s.setSeenCommitteeIndicesSlot(data.Slot, committeeIndex, att.GetAggregationBits()) msg.ValidatorData = att @@ -204,7 +218,7 @@ func (s *Service) validateUnaggregatedAttTopic(ctx context.Context, a eth.Att, b ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttTopic") defer span.End() - _, valCount, result, err := s.validateCommitteeIndexAndCount(ctx, a, bs) + _, valCount, result, err := s.validateCommitteeIndex(ctx, a, bs) if result != pubsub.ValidationAccept { return result, err } @@ -222,83 +236,93 @@ func (s *Service) validateUnaggregatedAttTopic(ctx context.Context, a eth.Att, b return pubsub.ValidationAccept, nil } -func (s *Service) validateCommitteeIndexAndCount( +func (s *Service) validateCommitteeIndex( ctx context.Context, a eth.Att, bs state.ReadOnlyBeaconState, ) (primitives.CommitteeIndex, uint64, pubsub.ValidationResult, error) { - ci, result, err := s.validateCommitteeIndex(ctx, a) - if result != pubsub.ValidationAccept { - return 0, 0, result, err + // - [REJECT] attestation.data.index == 0 + if a.Version() >= version.Electra && a.GetData().CommitteeIndex != 0 { + return 0, 0, pubsub.ValidationReject, errors.New("attestation data's committee index must be 0") } valCount, err := helpers.ActiveValidatorCount(ctx, bs, slots.ToEpoch(a.GetData().Slot)) if err != nil { return 0, 0, pubsub.ValidationIgnore, err } count := helpers.SlotCommitteeCount(valCount) + ci := a.GetCommitteeIndex() if uint64(ci) > count { - return 0, 0, pubsub.ValidationReject, fmt.Errorf("committee index %d > %d", a.GetData().CommitteeIndex, count) + return 0, 0, pubsub.ValidationReject, fmt.Errorf("committee index %d > %d", ci, count) } return ci, valCount, pubsub.ValidationAccept, nil } -func (s *Service) validateCommitteeIndex(ctx context.Context, a eth.Att) (primitives.CommitteeIndex, pubsub.ValidationResult, error) { +func validateAttesterData( + ctx context.Context, + a eth.Att, + committee []primitives.ValidatorIndex, +) (pubsub.ValidationResult, error) { if a.Version() >= version.Electra { - return validateCommitteeIndexElectra(ctx, a) + singleAtt, ok := a.(*eth.SingleAttestation) + if !ok { + return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, a) + } + result, err := validateAttestingIndex(ctx, singleAtt.AttesterIndex, committee) + if result != pubsub.ValidationAccept { + return result, err + } + } else { + // Verify number of aggregation bits matches the committee size. + if err := helpers.VerifyBitfieldLength(a.GetAggregationBits(), uint64(len(committee))); err != nil { + return pubsub.ValidationReject, err + } + // Attestation must be unaggregated and the bit index must exist in the range of committee indices. + // Note: The Ethereum Beacon chain spec suggests (len(get_attesting_indices(state, attestation.data, attestation.aggregation_bits)) == 1) + // however this validation can be achieved without use of get_attesting_indices which is an O(n) lookup. + if a.GetAggregationBits().Count() != 1 || a.GetAggregationBits().BitIndices()[0] >= len(committee) { + return pubsub.ValidationReject, errors.New("attestation bitfield is invalid") + } } - return a.GetData().CommitteeIndex, pubsub.ValidationAccept, nil + return pubsub.ValidationAccept, nil } -// This validates beacon unaggregated attestation using the given state, the validation consists of bitfield length and count consistency -// and signature verification. +// This validates beacon unaggregated attestation using the given state, the validation consists of signature verification. func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.Att, bs state.ReadOnlyBeaconState) (pubsub.ValidationResult, error) { ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttWithState") defer span.End() - committeeIndex, err := a.GetCommitteeIndex() - if err != nil { - return pubsub.ValidationIgnore, err - } - - committee, result, err := s.validateBitLength(ctx, bs, a.GetData().Slot, committeeIndex, a.GetAggregationBits()) - if result != pubsub.ValidationAccept { - return result, err - } - - // Attestation must be unaggregated and the bit index must exist in the range of committee indices. - // Note: The Ethereum Beacon chain spec suggests (len(get_attesting_indices(state, attestation.data, attestation.aggregation_bits)) == 1) - // however this validation can be achieved without use of get_attesting_indices which is an O(n) lookup. - if a.GetAggregationBits().Count() != 1 || a.GetAggregationBits().BitIndices()[0] >= len(committee) { - return pubsub.ValidationReject, errors.New("attestation bitfield is invalid") - } - set, err := blocks.AttestationSignatureBatch(ctx, bs, []eth.Att{a}) if err != nil { tracing.AnnotateError(span, err) attBadSignatureBatchCount.Inc() return pubsub.ValidationReject, err } + return s.validateWithBatchVerifier(ctx, "attestation", set) } -func (s *Service) validateBitLength( +func validateAttestingIndex( ctx context.Context, - bs state.ReadOnlyBeaconState, - slot primitives.Slot, - committeeIndex primitives.CommitteeIndex, - aggregationBits bitfield.Bitlist, -) ([]primitives.ValidatorIndex, pubsub.ValidationResult, error) { - committee, err := helpers.BeaconCommitteeFromState(ctx, bs, slot, committeeIndex) - if err != nil { - return nil, pubsub.ValidationIgnore, err - } + attestingIndex primitives.ValidatorIndex, + committee []primitives.ValidatorIndex, +) (pubsub.ValidationResult, error) { + _, span := trace.StartSpan(ctx, "sync.validateAttestingIndex") + defer span.End() - // Verify number of aggregation bits matches the committee size. - if err := helpers.VerifyBitfieldLength(aggregationBits, uint64(len(committee))); err != nil { - return nil, pubsub.ValidationReject, err + // _[REJECT]_ The attester is a member of the committee -- i.e. + // `attestation.attester_index in get_beacon_committee(state, attestation.data.slot, index)`. + inCommittee := false + for _, ix := range committee { + if attestingIndex == ix { + inCommittee = true + break + } + } + if !inCommittee { + return pubsub.ValidationReject, errors.New("attester is not a member of the committee") } - return committee, pubsub.ValidationAccept, nil + return pubsub.ValidationAccept, nil } // Returns true if the attestation was already seen for the participating validator for the slot. diff --git a/beacon-chain/sync/validate_beacon_attestation_electra.go b/beacon-chain/sync/validate_beacon_attestation_electra.go deleted file mode 100644 index 49c6fac2f5a4..000000000000 --- a/beacon-chain/sync/validate_beacon_attestation_electra.go +++ /dev/null @@ -1,28 +0,0 @@ -package sync - -import ( - "context" - "fmt" - - pubsub "github.com/libp2p/go-libp2p-pubsub" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" -) - -// validateCommitteeIndexElectra implements the following checks from the spec: -// - [REJECT] len(committee_indices) == 1, where committee_indices = get_committee_indices(attestation). -// - [REJECT] attestation.data.index == 0 -func validateCommitteeIndexElectra(ctx context.Context, a ethpb.Att) (primitives.CommitteeIndex, pubsub.ValidationResult, error) { - _, span := trace.StartSpan(ctx, "sync.validateCommitteeIndexElectra") - defer span.End() - _, ok := a.(*ethpb.AttestationElectra) - if !ok { - return 0, pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ðpb.AttestationElectra{}, a) - } - committeeIndex, err := a.GetCommitteeIndex() - if err != nil { - return 0, pubsub.ValidationReject, err - } - return committeeIndex, pubsub.ValidationAccept, nil -} diff --git a/beacon-chain/sync/validate_beacon_attestation_electra_test.go b/beacon-chain/sync/validate_beacon_attestation_electra_test.go deleted file mode 100644 index 81c8e2e9dff9..000000000000 --- a/beacon-chain/sync/validate_beacon_attestation_electra_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package sync - -import ( - "context" - "testing" - - pubsub "github.com/libp2p/go-libp2p-pubsub" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/assert" - "github.com/prysmaticlabs/prysm/v5/testing/require" -) - -func Test_validateCommitteeIndexElectra(t *testing.T) { - ctx := context.Background() - - t.Run("valid", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(1, true) - ci, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{}, CommitteeBits: cb}) - require.NoError(t, err) - assert.Equal(t, pubsub.ValidationAccept, res) - assert.Equal(t, primitives.CommitteeIndex(1), ci) - }) - t.Run("non-zero data committee index", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(1, true) - _, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{CommitteeIndex: 1}, CommitteeBits: cb}) - assert.NotNil(t, err) - assert.Equal(t, pubsub.ValidationReject, res) - }) - t.Run("no committee bits set", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - _, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{}, CommitteeBits: cb}) - assert.NotNil(t, err) - assert.Equal(t, pubsub.ValidationReject, res) - }) - t.Run("more than 1 committee bit set", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - cb.SetBitAt(1, true) - _, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{}, CommitteeBits: cb}) - assert.NotNil(t, err) - assert.Equal(t, pubsub.ValidationReject, res) - }) -} diff --git a/beacon-chain/sync/validate_beacon_attestation_test.go b/beacon-chain/sync/validate_beacon_attestation_test.go index 2451352fb421..f43566259f12 100644 --- a/beacon-chain/sync/validate_beacon_attestation_test.go +++ b/beacon-chain/sync/validate_beacon_attestation_test.go @@ -20,6 +20,7 @@ import ( lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -81,7 +82,7 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { tests := []struct { name string - msg *ethpb.Attestation + msg ethpb.Att topic string validAttestationSignature bool want bool @@ -262,20 +263,20 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { helpers.ClearCache() chain.ValidAttestation = tt.validAttestationSignature if tt.validAttestationSignature { - com, err := helpers.BeaconCommitteeFromState(context.Background(), savedState, tt.msg.Data.Slot, tt.msg.Data.CommitteeIndex) + com, err := helpers.BeaconCommitteeFromState(context.Background(), savedState, tt.msg.GetData().Slot, tt.msg.GetData().CommitteeIndex) require.NoError(t, err) - domain, err := signing.Domain(savedState.Fork(), tt.msg.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorsRoot()) + domain, err := signing.Domain(savedState.Fork(), tt.msg.GetData().Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorsRoot()) require.NoError(t, err) - attRoot, err := signing.ComputeSigningRoot(tt.msg.Data, domain) + attRoot, err := signing.ComputeSigningRoot(tt.msg.GetData(), domain) require.NoError(t, err) for i := 0; ; i++ { - if tt.msg.AggregationBits.BitAt(uint64(i)) { - tt.msg.Signature = keys[com[i]].Sign(attRoot[:]).Marshal() + if tt.msg.GetAggregationBits().BitAt(uint64(i)) { + tt.msg.SetSignature(keys[com[i]].Sign(attRoot[:]).Marshal()) break } } } else { - tt.msg.Signature = make([]byte, 96) + tt.msg.SetSignature(make([]byte, 96)) } buf := new(bytes.Buffer) _, err := p.Encoding().EncodeGossip(buf, tt.msg) @@ -305,6 +306,164 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { } } +func TestService_validateCommitteeIndexBeaconAttestationElectra(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + fvs := map[[fieldparams.VersionLength]byte]primitives.Epoch{} + fvs[bytesutil.ToBytes4(cfg.GenesisForkVersion)] = 1 + fvs[bytesutil.ToBytes4(cfg.AltairForkVersion)] = 2 + fvs[bytesutil.ToBytes4(cfg.BellatrixForkVersion)] = 3 + fvs[bytesutil.ToBytes4(cfg.CapellaForkVersion)] = 4 + fvs[bytesutil.ToBytes4(cfg.DenebForkVersion)] = 5 + fvs[bytesutil.ToBytes4(cfg.ElectraForkVersion)] = 0 + cfg.ForkVersionSchedule = fvs + params.OverrideBeaconConfig(cfg) + + p := p2ptest.NewTestP2P(t) + db := dbtest.SetupDB(t) + chain := &mockChain.ChainService{ + // 1 slot ago. + Genesis: time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second), + ValidatorsRoot: [32]byte{'A'}, + ValidAttestation: true, + DB: db, + Optimistic: true, + } + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + s := &Service{ + ctx: ctx, + cfg: &config{ + initialSync: &mockSync.Sync{IsSyncing: false}, + p2p: p, + beaconDB: db, + chain: chain, + clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), + attestationNotifier: (&mockChain.ChainService{}).OperationNotifier(), + }, + blkRootToPendingAtts: make(map[[32]byte][]ethpb.SignedAggregateAttAndProof), + seenUnAggregatedAttestationCache: lruwrpr.New(10), + signatureChan: make(chan *signatureVerifier, verifierLimit), + } + s.initCaches() + go s.verifierRoutine() + + digest, err := s.currentForkDigest() + require.NoError(t, err) + + blk := util.NewBeaconBlock() + blk.Block.Slot = 1 + util.SaveBlock(t, ctx, db, blk) + + validBlockRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + chain.FinalizedCheckPoint = ðpb.Checkpoint{ + Root: validBlockRoot[:], + Epoch: 0, + } + + validators := uint64(64) + savedState, keys := util.DeterministicGenesisState(t, validators) + require.NoError(t, savedState.SetSlot(1)) + require.NoError(t, db.SaveState(context.Background(), savedState, validBlockRoot)) + chain.State = savedState + committee, err := helpers.BeaconCommitteeFromState(ctx, savedState, 1, 0) + require.NoError(t, err) + + tests := []struct { + name string + msg ethpb.Att + want bool + }{ + { + name: "valid", + msg: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: validBlockRoot[:], + CommitteeIndex: 0, + Slot: 1, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: validBlockRoot[:], + }, + Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + }, + AttesterIndex: committee[0], + }, + want: true, + }, + { + name: "non-zero committee index in att data", + msg: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: validBlockRoot[:], + CommitteeIndex: 1, + Slot: 1, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: validBlockRoot[:], + }, + Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + }, + AttesterIndex: committee[0], + }, + want: false, + }, + { + name: "attesting index not in committee", + msg: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: validBlockRoot[:], + CommitteeIndex: 1, + Slot: 1, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: validBlockRoot[:], + }, + Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + }, + AttesterIndex: 999999, + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + helpers.ClearCache() + com, err := helpers.BeaconCommitteeFromState(context.Background(), savedState, tt.msg.GetData().Slot, tt.msg.GetData().CommitteeIndex) + require.NoError(t, err) + domain, err := signing.Domain(savedState.Fork(), tt.msg.GetData().Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorsRoot()) + require.NoError(t, err) + attRoot, err := signing.ComputeSigningRoot(tt.msg.GetData(), domain) + require.NoError(t, err) + tt.msg.SetSignature(keys[com[0]].Sign(attRoot[:]).Marshal()) + buf := new(bytes.Buffer) + _, err = p.Encoding().EncodeGossip(buf, tt.msg) + require.NoError(t, err) + topic := fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest) + m := &pubsub.Message{ + Message: &pubsubpb.Message{ + Data: buf.Bytes(), + Topic: &topic, + }, + } + + res, err := s.validateCommitteeIndexBeaconAttestation(ctx, "", m) + received := res == pubsub.ValidationAccept + if received != tt.want { + t.Fatalf("Did not received wanted validation. Got %v, wanted %v", !tt.want, tt.want) + } + if tt.want && err != nil { + t.Errorf("Non nil error returned: %v", err) + } + if tt.want && m.ValidatorData == nil { + t.Error("Expected validator data to be set") + } + }) + } +} + func TestService_setSeenCommitteeIndicesSlot(t *testing.T) { s := NewService(context.Background(), WithP2P(p2ptest.NewTestP2P(t))) s.initCaches() diff --git a/proto/prysm/v1alpha1/BUILD.bazel b/proto/prysm/v1alpha1/BUILD.bazel index fe510860a9c6..3a917a3bdd29 100644 --- a/proto/prysm/v1alpha1/BUILD.bazel +++ b/proto/prysm/v1alpha1/BUILD.bazel @@ -149,6 +149,7 @@ ssz_deneb_objs = [ ssz_electra_objs = [ "AggregateAttestationAndProofElectra", + "AggregateAttestationAndProofSingle", "AttestationElectra", "AttesterSlashingElectra", "BeaconBlockElectra", @@ -168,6 +169,7 @@ ssz_electra_objs = [ "PendingConsolidation", "PendingPartialWithdrawal", "SignedAggregateAttestationAndProofElectra", + "SignedAggregateAttestationAndProofSingle", "SignedBeaconBlockContentsElectra", "SignedBeaconBlockElectra", "SignedBlindedBeaconBlockElectra", @@ -375,8 +377,8 @@ ssz_proto_files( "beacon_block.proto", "beacon_state.proto", "blobs.proto", - "light_client.proto", "data_columns.proto", + "light_client.proto", "sync_committee.proto", "withdrawals.proto", ], diff --git a/proto/prysm/v1alpha1/attestation.go b/proto/prysm/v1alpha1/attestation.go index d5240294b446..493595d5a329 100644 --- a/proto/prysm/v1alpha1/attestation.go +++ b/proto/prysm/v1alpha1/attestation.go @@ -1,9 +1,6 @@ package eth import ( - "fmt" - - "github.com/pkg/errors" ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -20,14 +17,16 @@ type Att interface { ssz.HashRoot Version() int IsNil() bool + IsSingle() bool IsAggregated() bool Clone() Att GetAggregationBits() bitfield.Bitlist + GetAttestingIndex() primitives.ValidatorIndex GetData() *AttestationData CommitteeBitsVal() bitfield.Bitfield GetSignature() []byte SetSignature(sig []byte) - GetCommitteeIndex() (primitives.CommitteeIndex, error) + GetCommitteeIndex() primitives.CommitteeIndex } // IndexedAtt defines common functionality for all indexed attestation types. @@ -115,6 +114,11 @@ func (a *Attestation) IsNil() bool { return a == nil || a.Data == nil } +// IsSingle returns true when the attestation can have only a single attester index. +func (*Attestation) IsSingle() bool { + return false +} + // IsAggregated -- func (a *Attestation) IsAggregated() bool { return a.AggregationBits.Count() > 1 @@ -137,6 +141,11 @@ func (a *Attestation) Copy() *Attestation { } } +// GetAttestingIndex -- +func (*Attestation) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *Attestation) CommitteeBitsVal() bitfield.Bitfield { cb := primitives.NewAttestationCommitteeBits() @@ -150,11 +159,11 @@ func (a *Attestation) SetSignature(sig []byte) { } // GetCommitteeIndex -- -func (a *Attestation) GetCommitteeIndex() (primitives.CommitteeIndex, error) { +func (a *Attestation) GetCommitteeIndex() primitives.CommitteeIndex { if a == nil || a.Data == nil { - return 0, errors.New("nil attestation data") + return 0 } - return a.Data.CommitteeIndex, nil + return a.Data.CommitteeIndex } // Version -- @@ -167,6 +176,11 @@ func (a *PendingAttestation) IsNil() bool { return a == nil || a.Data == nil } +// IsSingle returns true when the attestation can have only a single attester index. +func (*PendingAttestation) IsSingle() bool { + return false +} + // IsAggregated -- func (a *PendingAttestation) IsAggregated() bool { return a.AggregationBits.Count() > 1 @@ -190,6 +204,11 @@ func (a *PendingAttestation) Copy() *PendingAttestation { } } +// GetAttestingIndex -- +func (*PendingAttestation) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *PendingAttestation) CommitteeBitsVal() bitfield.Bitfield { return nil @@ -204,11 +223,11 @@ func (a *PendingAttestation) GetSignature() []byte { func (a *PendingAttestation) SetSignature(_ []byte) {} // GetCommitteeIndex -- -func (a *PendingAttestation) GetCommitteeIndex() (primitives.CommitteeIndex, error) { +func (a *PendingAttestation) GetCommitteeIndex() primitives.CommitteeIndex { if a == nil || a.Data == nil { - return 0, errors.New("nil attestation data") + return 0 } - return a.Data.CommitteeIndex, nil + return a.Data.CommitteeIndex } // Version -- @@ -221,6 +240,11 @@ func (a *AttestationElectra) IsNil() bool { return a == nil || a.Data == nil } +// IsSingle returns true when the attestation can have only a single attester index. +func (*AttestationElectra) IsSingle() bool { + return false +} + // IsAggregated -- func (a *AttestationElectra) IsAggregated() bool { return a.AggregationBits.Count() > 1 @@ -244,6 +268,11 @@ func (a *AttestationElectra) Copy() *AttestationElectra { } } +// GetAttestingIndex -- +func (*AttestationElectra) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *AttestationElectra) CommitteeBitsVal() bitfield.Bitfield { return a.CommitteeBits @@ -255,21 +284,101 @@ func (a *AttestationElectra) SetSignature(sig []byte) { } // GetCommitteeIndex -- -func (a *AttestationElectra) GetCommitteeIndex() (primitives.CommitteeIndex, error) { - if a == nil || a.Data == nil { - return 0, errors.New("nil attestation data") - } +func (a *AttestationElectra) GetCommitteeIndex() primitives.CommitteeIndex { if len(a.CommitteeBits) == 0 { - return 0, errors.New("no committee bits found in attestation") - } - if a.Data.CommitteeIndex != 0 { - return 0, fmt.Errorf("attestation data's committee index must be 0 but was %d", a.Data.CommitteeIndex) + return 0 } indices := a.CommitteeBits.BitIndices() - if len(indices) != 1 { - return 0, fmt.Errorf("exactly 1 committee index must be set but %d were set", len(indices)) + if len(indices) == 0 { + return 0 + } + return primitives.CommitteeIndex(uint64(indices[0])) +} + +// Version -- +func (a *SingleAttestation) Version() int { + return version.Electra +} + +// IsNil -- +func (a *SingleAttestation) IsNil() bool { + return a == nil || a.Data == nil +} + +// IsAggregated -- +func (a *SingleAttestation) IsAggregated() bool { + return false +} + +// IsSingle returns true when the attestation can have only a single attester index. +func (*SingleAttestation) IsSingle() bool { + return true +} + +// Clone -- +func (a *SingleAttestation) Clone() Att { + return a.Copy() +} + +// Copy -- +func (a *SingleAttestation) Copy() *SingleAttestation { + if a == nil { + return nil + } + return &SingleAttestation{ + CommitteeId: a.CommitteeId, + AttesterIndex: a.AttesterIndex, + Data: a.Data.Copy(), + Signature: bytesutil.SafeCopyBytes(a.Signature), + } +} + +// GetAttestingIndex -- +func (a *SingleAttestation) GetAttestingIndex() primitives.ValidatorIndex { + return a.AttesterIndex +} + +// CommitteeBitsVal -- +func (a *SingleAttestation) CommitteeBitsVal() bitfield.Bitfield { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(uint64(a.CommitteeId), true) + return cb +} + +// GetAggregationBits -- +func (a *SingleAttestation) GetAggregationBits() bitfield.Bitlist { + return nil +} + +// SetSignature -- +func (a *SingleAttestation) SetSignature(sig []byte) { + a.Signature = sig +} + +// GetCommitteeIndex -- +func (a *SingleAttestation) GetCommitteeIndex() primitives.CommitteeIndex { + return a.CommitteeId +} + +// ToAttestationElectra converts the attestation to an AttestationElectra. +func (a *SingleAttestation) ToAttestationElectra(committee []primitives.ValidatorIndex) *AttestationElectra { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(uint64(a.CommitteeId), true) + + ab := bitfield.NewBitlist(uint64(len(committee))) + for i, ix := range committee { + if a.AttesterIndex == ix { + ab.SetBitAt(uint64(i), true) + break + } + } + + return &AttestationElectra{ + AggregationBits: ab, + Data: a.Data, + Signature: a.Signature, + CommitteeBits: cb, } - return primitives.CommitteeIndex(uint64(indices[0])), nil } // Version -- @@ -419,6 +528,21 @@ func (a *AggregateAttestationAndProofElectra) AggregateVal() Att { return a.Aggregate } +// Version -- +func (a *AggregateAttestationAndProofSingle) Version() int { + return version.Electra +} + +// IsNil -- +func (a *AggregateAttestationAndProofSingle) IsNil() bool { + return a == nil || a.Aggregate == nil || a.Aggregate.IsNil() +} + +// AggregateVal -- +func (a *AggregateAttestationAndProofSingle) AggregateVal() Att { + return a.Aggregate +} + // Version -- func (a *SignedAggregateAttestationAndProof) Version() int { return version.Phase0 @@ -448,3 +572,18 @@ func (a *SignedAggregateAttestationAndProofElectra) IsNil() bool { func (a *SignedAggregateAttestationAndProofElectra) AggregateAttestationAndProof() AggregateAttAndProof { return a.Message } + +// Version -- +func (a *SignedAggregateAttestationAndProofSingle) Version() int { + return version.Electra +} + +// IsNil -- +func (a *SignedAggregateAttestationAndProofSingle) IsNil() bool { + return a == nil || a.Message == nil || a.Message.IsNil() +} + +// AggregateAttestationAndProof -- +func (a *SignedAggregateAttestationAndProofSingle) AggregateAttestationAndProof() AggregateAttAndProof { + return a.Message +} diff --git a/proto/prysm/v1alpha1/attestation.pb.go b/proto/prysm/v1alpha1/attestation.pb.go index 8bb6572d6236..f8c6fa5f92cf 100755 --- a/proto/prysm/v1alpha1/attestation.pb.go +++ b/proto/prysm/v1alpha1/attestation.pb.go @@ -528,6 +528,124 @@ func (x *AttestationElectra) GetCommitteeBits() github_com_prysmaticlabs_go_bitf return github_com_prysmaticlabs_go_bitfield.Bitvector64(nil) } +type SignedAggregateAttestationAndProofSingle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *AggregateAttestationAndProofSingle `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SignedAggregateAttestationAndProofSingle) Reset() { + *x = SignedAggregateAttestationAndProofSingle{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedAggregateAttestationAndProofSingle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedAggregateAttestationAndProofSingle) ProtoMessage() {} + +func (x *SignedAggregateAttestationAndProofSingle) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedAggregateAttestationAndProofSingle.ProtoReflect.Descriptor instead. +func (*SignedAggregateAttestationAndProofSingle) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{8} +} + +func (x *SignedAggregateAttestationAndProofSingle) GetMessage() *AggregateAttestationAndProofSingle { + if x != nil { + return x.Message + } + return nil +} + +func (x *SignedAggregateAttestationAndProofSingle) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +type AggregateAttestationAndProofSingle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AggregatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=aggregator_index,json=aggregatorIndex,proto3" json:"aggregator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + Aggregate *SingleAttestation `protobuf:"bytes,3,opt,name=aggregate,proto3" json:"aggregate,omitempty"` + SelectionProof []byte `protobuf:"bytes,2,opt,name=selection_proof,json=selectionProof,proto3" json:"selection_proof,omitempty" ssz-size:"96"` +} + +func (x *AggregateAttestationAndProofSingle) Reset() { + *x = AggregateAttestationAndProofSingle{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AggregateAttestationAndProofSingle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AggregateAttestationAndProofSingle) ProtoMessage() {} + +func (x *AggregateAttestationAndProofSingle) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AggregateAttestationAndProofSingle.ProtoReflect.Descriptor instead. +func (*AggregateAttestationAndProofSingle) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{9} +} + +func (x *AggregateAttestationAndProofSingle) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { + if x != nil { + return x.AggregatorIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *AggregateAttestationAndProofSingle) GetAggregate() *SingleAttestation { + if x != nil { + return x.Aggregate + } + return nil +} + +func (x *AggregateAttestationAndProofSingle) GetSelectionProof() []byte { + if x != nil { + return x.SelectionProof + } + return nil +} + type SingleAttestation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -542,7 +660,7 @@ type SingleAttestation struct { func (x *SingleAttestation) Reset() { *x = SingleAttestation{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -555,7 +673,7 @@ func (x *SingleAttestation) String() string { func (*SingleAttestation) ProtoMessage() {} func (x *SingleAttestation) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -568,7 +686,7 @@ func (x *SingleAttestation) ProtoReflect() protoreflect.Message { // Deprecated: Use SingleAttestation.ProtoReflect.Descriptor instead. func (*SingleAttestation) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{8} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{10} } func (x *SingleAttestation) GetCommitteeId() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex { @@ -730,39 +848,68 @@ var file_proto_prysm_v1alpha1_attestation_proto_rawDesc = []byte{ 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x36, 0x34, 0x8a, 0xb5, 0x18, 0x01, 0x38, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x42, 0x69, 0x74, 0x73, 0x22, 0xe1, 0x02, 0x0a, 0x11, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x72, 0x0a, 0x0c, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x64, 0x12, - 0x76, 0x0a, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, - 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, - 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x42, 0x69, 0x74, 0x73, 0x22, 0xa5, 0x01, 0x0a, 0x28, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x53, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x12, 0x53, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x99, 0x02, + 0x0a, 0x22, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x53, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x12, 0x7a, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, + 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, + 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x46, 0x0a, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0xe1, 0x02, 0x0a, 0x11, 0x53, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x72, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x64, 0x12, 0x76, 0x0a, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, + 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3a, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x9b, 0x01, + 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, + 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -777,7 +924,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP() []byte { return file_proto_prysm_v1alpha1_attestation_proto_rawDescData } -var file_proto_prysm_v1alpha1_attestation_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_proto_prysm_v1alpha1_attestation_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_proto_prysm_v1alpha1_attestation_proto_goTypes = []interface{}{ (*SignedAggregateAttestationAndProof)(nil), // 0: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof (*AggregateAttestationAndProof)(nil), // 1: ethereum.eth.v1alpha1.AggregateAttestationAndProof @@ -787,23 +934,27 @@ var file_proto_prysm_v1alpha1_attestation_proto_goTypes = []interface{}{ (*SignedAggregateAttestationAndProofElectra)(nil), // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra (*AggregateAttestationAndProofElectra)(nil), // 6: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra (*AttestationElectra)(nil), // 7: ethereum.eth.v1alpha1.AttestationElectra - (*SingleAttestation)(nil), // 8: ethereum.eth.v1alpha1.SingleAttestation + (*SignedAggregateAttestationAndProofSingle)(nil), // 8: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofSingle + (*AggregateAttestationAndProofSingle)(nil), // 9: ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle + (*SingleAttestation)(nil), // 10: ethereum.eth.v1alpha1.SingleAttestation } var file_proto_prysm_v1alpha1_attestation_proto_depIdxs = []int32{ - 1, // 0: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof - 2, // 1: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation - 3, // 2: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 4, // 3: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint - 4, // 4: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint - 6, // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - 7, // 6: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra - 3, // 7: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 3, // 8: ethereum.eth.v1alpha1.SingleAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 1, // 0: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof + 2, // 1: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation + 3, // 2: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 4, // 3: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint + 4, // 4: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint + 6, // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + 7, // 6: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra + 3, // 7: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 9, // 8: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofSingle.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle + 10, // 9: ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle.aggregate:type_name -> ethereum.eth.v1alpha1.SingleAttestation + 3, // 10: ethereum.eth.v1alpha1.SingleAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_proto_prysm_v1alpha1_attestation_proto_init() } @@ -909,6 +1060,30 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignedAggregateAttestationAndProofSingle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_attestation_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AggregateAttestationAndProofSingle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_attestation_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SingleAttestation); i { case 0: return &v.state @@ -927,7 +1102,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_prysm_v1alpha1_attestation_proto_rawDesc, NumEnums: 0, - NumMessages: 9, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/prysm/v1alpha1/attestation.proto b/proto/prysm/v1alpha1/attestation.proto index b48c58574f32..f3429a37b1b0 100644 --- a/proto/prysm/v1alpha1/attestation.proto +++ b/proto/prysm/v1alpha1/attestation.proto @@ -126,6 +126,25 @@ message AttestationElectra { bytes committee_bits = 4 [(ethereum.eth.ext.ssz_size) = "committee_bits.size", (ethereum.eth.ext.cast_type) = "committee_bits.type"]; } +message SignedAggregateAttestationAndProofSingle { + // The aggregated attestation and selection proof itself. + AggregateAttestationAndProofSingle message = 1; + + // 96 byte BLS aggregate signature signed by the aggregator over the message. + bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; +} + +message AggregateAttestationAndProofSingle { + // The aggregator index that submitted this aggregated attestation and proof. + uint64 aggregator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + + // The aggregated attestation that was submitted. + SingleAttestation aggregate = 3; + + // 96 byte selection proof signed by the aggregator, which is the signature of the slot to aggregate. + bytes selection_proof = 2 [(ethereum.eth.ext.ssz_size) = "96"]; +} + message SingleAttestation { uint64 committee_id = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; uint64 attester_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; diff --git a/proto/prysm/v1alpha1/electra.ssz.go b/proto/prysm/v1alpha1/electra.ssz.go index 1029c5cde25a..2016b77baeeb 100644 --- a/proto/prysm/v1alpha1/electra.ssz.go +++ b/proto/prysm/v1alpha1/electra.ssz.go @@ -383,6 +383,181 @@ func (a *AttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } +// MarshalSSZ ssz marshals the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedAggregateAttestationAndProofSingle object to a target array +func (s *SignedAggregateAttestationAndProofSingle) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(AggregateAttestationAndProofSingle) + } + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 440 { + return ssz.ErrSize + } + + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(AggregateAttestationAndProofSingle) + } + if err = s.Message.UnmarshalSSZ(buf[0:344]); err != nil { + return err + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[344:440])) + } + s.Signature = append(s.Signature, buf[344:440]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) SizeSSZ() (size int) { + size = 440 + return +} + +// HashTreeRoot ssz hashes the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedAggregateAttestationAndProofSingle object with a hasher +func (s *SignedAggregateAttestationAndProofSingle) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(a) +} + +// MarshalSSZTo ssz marshals the AggregateAttestationAndProofSingle object to a target array +func (a *AggregateAttestationAndProofSingle) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'AggregatorIndex' + dst = ssz.MarshalUint64(dst, uint64(a.AggregatorIndex)) + + // Field (1) 'Aggregate' + if a.Aggregate == nil { + a.Aggregate = new(SingleAttestation) + } + if dst, err = a.Aggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'SelectionProof' + if size := len(a.SelectionProof); size != 96 { + err = ssz.ErrBytesLengthFn("--.SelectionProof", size, 96) + return + } + dst = append(dst, a.SelectionProof...) + + return +} + +// UnmarshalSSZ ssz unmarshals the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 344 { + return ssz.ErrSize + } + + // Field (0) 'AggregatorIndex' + a.AggregatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'Aggregate' + if a.Aggregate == nil { + a.Aggregate = new(SingleAttestation) + } + if err = a.Aggregate.UnmarshalSSZ(buf[8:248]); err != nil { + return err + } + + // Field (2) 'SelectionProof' + if cap(a.SelectionProof) == 0 { + a.SelectionProof = make([]byte, 0, len(buf[248:344])) + } + a.SelectionProof = append(a.SelectionProof, buf[248:344]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) SizeSSZ() (size int) { + size = 344 + return +} + +// HashTreeRoot ssz hashes the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(a) +} + +// HashTreeRootWith ssz hashes the AggregateAttestationAndProofSingle object with a hasher +func (a *AggregateAttestationAndProofSingle) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AggregatorIndex' + hh.PutUint64(uint64(a.AggregatorIndex)) + + // Field (1) 'Aggregate' + if err = a.Aggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'SelectionProof' + if size := len(a.SelectionProof); size != 96 { + err = ssz.ErrBytesLengthFn("--.SelectionProof", size, 96) + return + } + hh.PutBytes(a.SelectionProof) + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the SingleAttestation object func (s *SingleAttestation) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(s) diff --git a/proto/prysm/v1alpha1/validator.pb.go b/proto/prysm/v1alpha1/validator.pb.go index f0e5cec84a48..e6787fa5e39a 100755 --- a/proto/prysm/v1alpha1/validator.pb.go +++ b/proto/prysm/v1alpha1/validator.pb.go @@ -3728,7 +3728,7 @@ var file_proto_prysm_v1alpha1_validator_proto_rawDesc = []byte{ 0x0a, 0x0a, 0x06, 0x45, 0x58, 0x49, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x41, 0x52, 0x54, 0x49, 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x44, 0x10, - 0x08, 0x32, 0xf5, 0x28, 0x0a, 0x13, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, + 0x08, 0x32, 0xf4, 0x28, 0x0a, 0x13, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x80, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, @@ -3856,216 +3856,216 @@ var file_proto_prysm_v1alpha1_validator_proto_rawDesc = []byte{ 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x3a, 0x01, 0x2a, 0x22, 0x23, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0xa5, 0x01, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, + 0x69, 0x6f, 0x6e, 0x12, 0xa4, 0x01, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, - 0x61, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x1a, 0x25, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x3a, 0x01, 0x2a, 0x22, 0x2b, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xb2, 0x01, 0x0a, 0x1d, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x30, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x12, 0xc8, 0x01, 0x0a, 0x24, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x65, 0x74, + 0x61, 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, - 0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xbe, 0x01, 0x0a, 0x23, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x3a, 0x01, 0x2a, 0x22, 0x2b, 0x2f, + 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xb2, 0x01, 0x0a, 0x1d, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x30, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, + 0xc8, 0x01, 0x0a, 0x24, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xd4, 0x01, 0x0a, - 0x2a, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, - 0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3a, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, + 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, + 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xbe, 0x01, 0x0a, 0x23, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, + 0x6f, 0x66, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x72, 0x61, 0x12, 0x8e, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, - 0x78, 0x69, 0x74, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a, - 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, - 0x78, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, - 0x65, 0x78, 0x69, 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, - 0x74, 0x73, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x2f, 0x73, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x9a, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x2a, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, - 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, + 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xd4, 0x01, 0x0a, 0x2a, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, - 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x67, - 0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x9f, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, - 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, - 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, - 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x72, 0x61, 0x12, 0x8e, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, + 0x69, 0x74, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a, 0x2a, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, + 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x65, + 0x78, 0x69, 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, + 0x73, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, + 0x74, 0x79, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0xb4, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x53, - 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, - 0x6e, 0x63, 0x53, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0xc4, 0x01, 0x0a, 0x1c, 0x47, - 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, - 0x2a, 0x22, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, - 0x66, 0x12, 0xaf, 0x01, 0x0a, 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, - 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x9a, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x2a, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, + 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x67, 0x61, + 0x6e, 0x67, 0x65, 0x72, 0x12, 0x9f, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, + 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x40, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x3a, 0x01, 0x2a, 0x22, 0x35, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x12, 0x9e, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, - 0x6f, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x2d, 0x12, 0x2b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x88, - 0x02, 0x01, 0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, + 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x9e, 0x01, 0x0a, 0x1c, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, - 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xae, 0x01, 0x0a, 0x17, 0x41, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x3a, 0x01, 0x2a, 0x22, - 0x39, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, - 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0xec, 0x01, 0x0a, 0x1f, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3d, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0xb4, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, + 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, + 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x53, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0xc4, 0x01, 0x0a, 0x1c, 0x47, 0x65, + 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, 0x2a, + 0x22, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x12, 0xaf, 0x01, 0x0a, 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, + 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x40, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x3a, 0x01, 0x2a, 0x22, 0x35, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, + 0x6f, 0x66, 0x12, 0x9e, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, + 0x74, 0x73, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x2d, 0x12, 0x2b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x73, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x88, 0x02, + 0x01, 0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x9e, 0x01, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, + 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xae, 0x01, 0x0a, 0x17, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, + 0x62, 0x6e, 0x65, 0x74, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, + 0x62, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x3a, 0x01, 0x2a, 0x22, 0x39, + 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x61, + 0x73, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, + 0x74, 0x6f, 0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0xec, 0x01, 0x0a, 0x1f, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x12, 0x42, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x73, 0x69, 0x67, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x42, 0x93, 0x01, 0x0a, 0x19, 0x6f, 0x72, - 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, + 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x44, 0x12, 0x42, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x73, 0x69, 0x67, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x42, 0x93, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4149,7 +4149,7 @@ var file_proto_prysm_v1alpha1_validator_proto_goTypes = []interface{}{ (*emptypb.Empty)(nil), // 63: google.protobuf.Empty (*GenericSignedBeaconBlock)(nil), // 64: ethereum.eth.v1alpha1.GenericSignedBeaconBlock (*Attestation)(nil), // 65: ethereum.eth.v1alpha1.Attestation - (*AttestationElectra)(nil), // 66: ethereum.eth.v1alpha1.AttestationElectra + (*SingleAttestation)(nil), // 66: ethereum.eth.v1alpha1.SingleAttestation (*SignedVoluntaryExit)(nil), // 67: ethereum.eth.v1alpha1.SignedVoluntaryExit (*SignedContributionAndProof)(nil), // 68: ethereum.eth.v1alpha1.SignedContributionAndProof (*SignedValidatorRegistrationsV1)(nil), // 69: ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1 @@ -4195,7 +4195,7 @@ var file_proto_prysm_v1alpha1_validator_proto_depIdxs = []int32{ 41, // 34: ethereum.eth.v1alpha1.BeaconNodeValidator.GetFeeRecipientByPubKey:input_type -> ethereum.eth.v1alpha1.FeeRecipientByPubKeyRequest 24, // 35: ethereum.eth.v1alpha1.BeaconNodeValidator.GetAttestationData:input_type -> ethereum.eth.v1alpha1.AttestationDataRequest 65, // 36: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestation:input_type -> ethereum.eth.v1alpha1.Attestation - 66, // 37: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestationElectra:input_type -> ethereum.eth.v1alpha1.AttestationElectra + 66, // 37: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestationElectra:input_type -> ethereum.eth.v1alpha1.SingleAttestation 26, // 38: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProof:input_type -> ethereum.eth.v1alpha1.AggregateSelectionRequest 26, // 39: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProofElectra:input_type -> ethereum.eth.v1alpha1.AggregateSelectionRequest 29, // 40: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProof:input_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitRequest @@ -4917,7 +4917,7 @@ type BeaconNodeValidatorClient interface { GetFeeRecipientByPubKey(ctx context.Context, in *FeeRecipientByPubKeyRequest, opts ...grpc.CallOption) (*FeeRecipientByPubKeyResponse, error) GetAttestationData(ctx context.Context, in *AttestationDataRequest, opts ...grpc.CallOption) (*AttestationData, error) ProposeAttestation(ctx context.Context, in *Attestation, opts ...grpc.CallOption) (*AttestResponse, error) - ProposeAttestationElectra(ctx context.Context, in *AttestationElectra, opts ...grpc.CallOption) (*AttestResponse, error) + ProposeAttestationElectra(ctx context.Context, in *SingleAttestation, opts ...grpc.CallOption) (*AttestResponse, error) SubmitAggregateSelectionProof(ctx context.Context, in *AggregateSelectionRequest, opts ...grpc.CallOption) (*AggregateSelectionResponse, error) SubmitAggregateSelectionProofElectra(ctx context.Context, in *AggregateSelectionRequest, opts ...grpc.CallOption) (*AggregateSelectionElectraResponse, error) SubmitSignedAggregateSelectionProof(ctx context.Context, in *SignedAggregateSubmitRequest, opts ...grpc.CallOption) (*SignedAggregateSubmitResponse, error) @@ -5112,7 +5112,7 @@ func (c *beaconNodeValidatorClient) ProposeAttestation(ctx context.Context, in * return out, nil } -func (c *beaconNodeValidatorClient) ProposeAttestationElectra(ctx context.Context, in *AttestationElectra, opts ...grpc.CallOption) (*AttestResponse, error) { +func (c *beaconNodeValidatorClient) ProposeAttestationElectra(ctx context.Context, in *SingleAttestation, opts ...grpc.CallOption) (*AttestResponse, error) { out := new(AttestResponse) err := c.cc.Invoke(ctx, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestationElectra", in, out, opts...) if err != nil { @@ -5339,7 +5339,7 @@ type BeaconNodeValidatorServer interface { GetFeeRecipientByPubKey(context.Context, *FeeRecipientByPubKeyRequest) (*FeeRecipientByPubKeyResponse, error) GetAttestationData(context.Context, *AttestationDataRequest) (*AttestationData, error) ProposeAttestation(context.Context, *Attestation) (*AttestResponse, error) - ProposeAttestationElectra(context.Context, *AttestationElectra) (*AttestResponse, error) + ProposeAttestationElectra(context.Context, *SingleAttestation) (*AttestResponse, error) SubmitAggregateSelectionProof(context.Context, *AggregateSelectionRequest) (*AggregateSelectionResponse, error) SubmitAggregateSelectionProofElectra(context.Context, *AggregateSelectionRequest) (*AggregateSelectionElectraResponse, error) SubmitSignedAggregateSelectionProof(context.Context, *SignedAggregateSubmitRequest) (*SignedAggregateSubmitResponse, error) @@ -5404,7 +5404,7 @@ func (*UnimplementedBeaconNodeValidatorServer) GetAttestationData(context.Contex func (*UnimplementedBeaconNodeValidatorServer) ProposeAttestation(context.Context, *Attestation) (*AttestResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProposeAttestation not implemented") } -func (*UnimplementedBeaconNodeValidatorServer) ProposeAttestationElectra(context.Context, *AttestationElectra) (*AttestResponse, error) { +func (*UnimplementedBeaconNodeValidatorServer) ProposeAttestationElectra(context.Context, *SingleAttestation) (*AttestResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProposeAttestationElectra not implemented") } func (*UnimplementedBeaconNodeValidatorServer) SubmitAggregateSelectionProof(context.Context, *AggregateSelectionRequest) (*AggregateSelectionResponse, error) { @@ -5704,7 +5704,7 @@ func _BeaconNodeValidator_ProposeAttestation_Handler(srv interface{}, ctx contex } func _BeaconNodeValidator_ProposeAttestationElectra_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AttestationElectra) + in := new(SingleAttestation) if err := dec(in); err != nil { return nil, err } @@ -5716,7 +5716,7 @@ func _BeaconNodeValidator_ProposeAttestationElectra_Handler(srv interface{}, ctx FullMethod: "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestationElectra", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BeaconNodeValidatorServer).ProposeAttestationElectra(ctx, req.(*AttestationElectra)) + return srv.(BeaconNodeValidatorServer).ProposeAttestationElectra(ctx, req.(*SingleAttestation)) } return interceptor(ctx, in, info, handler) } diff --git a/proto/prysm/v1alpha1/validator.proto b/proto/prysm/v1alpha1/validator.proto index d4d68d702851..c38d930c4895 100644 --- a/proto/prysm/v1alpha1/validator.proto +++ b/proto/prysm/v1alpha1/validator.proto @@ -194,7 +194,7 @@ service BeaconNodeValidator { // The validator sends the newly signed attestation to the beacon node for the attestation to // be included in the beacon chain. The beacon node is expected to validate and publish attestation on // appropriate committee subnet. - rpc ProposeAttestationElectra(AttestationElectra) returns (AttestResponse) { + rpc ProposeAttestationElectra(SingleAttestation) returns (AttestResponse) { option (google.api.http) = { post: "/eth/v1alpha1/validator/attestation_electra" body: "*" diff --git a/testing/mock/beacon_service_mock.go b/testing/mock/beacon_service_mock.go index 49b8b66d46d9..f5e506ba34d2 100644 --- a/testing/mock/beacon_service_mock.go +++ b/testing/mock/beacon_service_mock.go @@ -429,7 +429,7 @@ func (m *MockBeaconChainClient) SubmitAttesterSlashing(arg0 context.Context, arg for _, a := range arg2 { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "SubmitAttesterSlashings", varargs...) + ret := m.ctrl.Call(m, "SubmitAttesterSlashing", varargs...) ret0, _ := ret[0].(*eth.SubmitSlashingResponse) ret1, _ := ret[1].(error) return ret0, ret1 @@ -439,7 +439,7 @@ func (m *MockBeaconChainClient) SubmitAttesterSlashing(arg0 context.Context, arg func (mr *MockBeaconChainClientMockRecorder) SubmitAttesterSlashing(arg0, arg1 any, arg2 ...any) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]any{arg0, arg1}, arg2...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitAttesterSlashings", reflect.TypeOf((*MockBeaconChainClient)(nil).SubmitAttesterSlashing), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitAttesterSlashing", reflect.TypeOf((*MockBeaconChainClient)(nil).SubmitAttesterSlashing), varargs...) } // SubmitAttesterSlashingElectra mocks base method. diff --git a/testing/mock/beacon_validator_client_mock.go b/testing/mock/beacon_validator_client_mock.go index 233e91c8ffc6..d104bb76439b 100644 --- a/testing/mock/beacon_validator_client_mock.go +++ b/testing/mock/beacon_validator_client_mock.go @@ -324,7 +324,7 @@ func (mr *MockBeaconNodeValidatorClientMockRecorder) ProposeAttestation(arg0, ar } // ProposeAttestationElectra mocks base method. -func (m *MockBeaconNodeValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.AttestationElectra, arg2 ...grpc.CallOption) (*eth.AttestResponse, error) { +func (m *MockBeaconNodeValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.SingleAttestation, arg2 ...grpc.CallOption) (*eth.AttestResponse, error) { m.ctrl.T.Helper() varargs := []any{arg0, arg1} for _, a := range arg2 { @@ -786,6 +786,129 @@ func (mr *MockBeaconNodeValidator_WaitForChainStartClientMockRecorder) Trailer() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockBeaconNodeValidator_WaitForChainStartClient)(nil).Trailer)) } +// MockBeaconNodeValidator_WaitForActivationClient is a mock of BeaconNodeValidator_WaitForActivationClient interface. +type MockBeaconNodeValidator_WaitForActivationClient struct { + ctrl *gomock.Controller + recorder *MockBeaconNodeValidator_WaitForActivationClientMockRecorder +} + +// MockBeaconNodeValidator_WaitForActivationClientMockRecorder is the mock recorder for MockBeaconNodeValidator_WaitForActivationClient. +type MockBeaconNodeValidator_WaitForActivationClientMockRecorder struct { + mock *MockBeaconNodeValidator_WaitForActivationClient +} + +// NewMockBeaconNodeValidator_WaitForActivationClient creates a new mock instance. +func NewMockBeaconNodeValidator_WaitForActivationClient(ctrl *gomock.Controller) *MockBeaconNodeValidator_WaitForActivationClient { + mock := &MockBeaconNodeValidator_WaitForActivationClient{ctrl: ctrl} + mock.recorder = &MockBeaconNodeValidator_WaitForActivationClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBeaconNodeValidator_WaitForActivationClient) EXPECT() *MockBeaconNodeValidator_WaitForActivationClientMockRecorder { + return m.recorder +} + +// CloseSend mocks base method. +func (m *MockBeaconNodeValidator_WaitForActivationClient) CloseSend() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CloseSend") + ret0, _ := ret[0].(error) + return ret0 +} + +// CloseSend indicates an expected call of CloseSend. +func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) CloseSend() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).CloseSend)) +} + +// Context mocks base method. +func (m *MockBeaconNodeValidator_WaitForActivationClient) Context() context.Context { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Context") + ret0, _ := ret[0].(context.Context) + return ret0 +} + +// Context indicates an expected call of Context. +func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Context() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Context)) +} + +// Header mocks base method. +func (m *MockBeaconNodeValidator_WaitForActivationClient) Header() (metadata.MD, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Header") + ret0, _ := ret[0].(metadata.MD) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Header indicates an expected call of Header. +func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Header() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Header)) +} + +// Recv mocks base method. +func (m *MockBeaconNodeValidator_WaitForActivationClient) Recv() (*eth.ValidatorActivationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Recv") + ret0, _ := ret[0].(*eth.ValidatorActivationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Recv indicates an expected call of Recv. +func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Recv() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recv", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Recv)) +} + +// RecvMsg mocks base method. +func (m *MockBeaconNodeValidator_WaitForActivationClient) RecvMsg(arg0 any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RecvMsg", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RecvMsg indicates an expected call of RecvMsg. +func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) RecvMsg(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).RecvMsg), arg0) +} + +// SendMsg mocks base method. +func (m *MockBeaconNodeValidator_WaitForActivationClient) SendMsg(arg0 any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendMsg", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendMsg indicates an expected call of SendMsg. +func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) SendMsg(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).SendMsg), arg0) +} + +// Trailer mocks base method. +func (m *MockBeaconNodeValidator_WaitForActivationClient) Trailer() metadata.MD { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Trailer") + ret0, _ := ret[0].(metadata.MD) + return ret0 +} + +// Trailer indicates an expected call of Trailer. +func (mr *MockBeaconNodeValidator_WaitForActivationClientMockRecorder) Trailer() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockBeaconNodeValidator_WaitForActivationClient)(nil).Trailer)) +} + // MockBeaconNodeValidator_StreamSlotsClient is a mock of BeaconNodeValidator_StreamSlotsClient interface. type MockBeaconNodeValidator_StreamSlotsClient struct { ctrl *gomock.Controller diff --git a/testing/mock/beacon_validator_server_mock.go b/testing/mock/beacon_validator_server_mock.go index 9643784dfc27..d610f37b9c00 100644 --- a/testing/mock/beacon_validator_server_mock.go +++ b/testing/mock/beacon_validator_server_mock.go @@ -253,7 +253,7 @@ func (mr *MockBeaconNodeValidatorServerMockRecorder) ProposeAttestation(arg0, ar } // ProposeAttestationElectra mocks base method. -func (m *MockBeaconNodeValidatorServer) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.AttestationElectra) (*eth.AttestResponse, error) { +func (m *MockBeaconNodeValidatorServer) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.SingleAttestation) (*eth.AttestResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProposeAttestationElectra", arg0, arg1) ret0, _ := ret[0].(*eth.AttestResponse) diff --git a/testing/validator-mock/validator_client_mock.go b/testing/validator-mock/validator_client_mock.go index afbe08b5e2a3..274ebb39d6c7 100644 --- a/testing/validator-mock/validator_client_mock.go +++ b/testing/validator-mock/validator_client_mock.go @@ -181,7 +181,7 @@ func (mr *MockValidatorClientMockRecorder) FeeRecipientByPubKey(arg0, arg1 any) // Host mocks base method. func (m *MockValidatorClient) Host() string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HTTPHost") + ret := m.ctrl.Call(m, "Host") ret0, _ := ret[0].(string) return ret0 } @@ -189,7 +189,7 @@ func (m *MockValidatorClient) Host() string { // Host indicates an expected call of Host. func (mr *MockValidatorClientMockRecorder) Host() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HTTPHost", reflect.TypeOf((*MockValidatorClient)(nil).Host)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockValidatorClient)(nil).Host)) } // MultipleValidatorStatus mocks base method. @@ -238,7 +238,7 @@ func (mr *MockValidatorClientMockRecorder) ProposeAttestation(arg0, arg1 any) *g } // ProposeAttestationElectra mocks base method. -func (m *MockValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.AttestationElectra) (*eth.AttestResponse, error) { +func (m *MockValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.SingleAttestation) (*eth.AttestResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProposeAttestationElectra", arg0, arg1) ret0, _ := ret[0].(*eth.AttestResponse) @@ -501,21 +501,6 @@ func (mr *MockValidatorClientMockRecorder) ValidatorStatus(arg0, arg1 any) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorStatus", reflect.TypeOf((*MockValidatorClient)(nil).ValidatorStatus), arg0, arg1) } -// WaitForActivation mocks base method. -func (m *MockValidatorClient) WaitForActivation(arg0 context.Context, arg1 *eth.ValidatorActivationRequest) (eth.BeaconNodeValidator_WaitForActivationClient, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WaitForActivation", arg0, arg1) - ret0, _ := ret[0].(eth.BeaconNodeValidator_WaitForActivationClient) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// WaitForActivation indicates an expected call of WaitForActivation. -func (mr *MockValidatorClientMockRecorder) WaitForActivation(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForActivation", reflect.TypeOf((*MockValidatorClient)(nil).WaitForActivation), arg0, arg1) -} - // WaitForChainStart mocks base method. func (m *MockValidatorClient) WaitForChainStart(arg0 context.Context, arg1 *emptypb.Empty) (*eth.ChainStartResponse, error) { m.ctrl.T.Helper() diff --git a/validator/client/attest.go b/validator/client/attest.go index 0c2f92a83cc6..1ec917aa4736 100644 --- a/validator/client/attest.go +++ b/validator/client/attest.go @@ -122,23 +122,6 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, return } - var indexInCommittee uint64 - var found bool - for i, vID := range duty.Committee { - if vID == duty.ValidatorIndex { - indexInCommittee = uint64(i) - found = true - break - } - } - if !found { - log.Errorf("Validator ID %d not found in committee of %v", duty.ValidatorIndex, duty.Committee) - if v.emitAccountMetrics { - ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc() - } - return - } - // TODO: Extend to Electra phase0Att, ok := indexedAtt.(*ethpb.IndexedAttestation) if ok { @@ -153,21 +136,36 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, } } - aggregationBitfield := bitfield.NewBitlist(uint64(len(duty.Committee))) - aggregationBitfield.SetBitAt(indexInCommittee, true) - committeeBits := primitives.NewAttestationCommitteeBits() + var aggregationBitfield bitfield.Bitlist var attResp *ethpb.AttestResponse if postElectra { - attestation := ðpb.AttestationElectra{ - Data: data, - AggregationBits: aggregationBitfield, - CommitteeBits: committeeBits, - Signature: sig, + attestation := ðpb.SingleAttestation{ + Data: data, + AttesterIndex: duty.ValidatorIndex, + CommitteeId: duty.CommitteeIndex, + Signature: sig, } - attestation.CommitteeBits.SetBitAt(uint64(req.CommitteeIndex), true) attResp, err = v.validatorClient.ProposeAttestationElectra(ctx, attestation) } else { + var indexInCommittee uint64 + var found bool + for i, vID := range duty.Committee { + if vID == duty.ValidatorIndex { + indexInCommittee = uint64(i) + found = true + break + } + } + if !found { + log.Errorf("Validator ID %d not found in committee of %v", duty.ValidatorIndex, duty.Committee) + if v.emitAccountMetrics { + ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc() + } + return + } + aggregationBitfield = bitfield.NewBitlist(uint64(len(duty.Committee))) + aggregationBitfield.SetBitAt(indexInCommittee, true) attestation := ðpb.Attestation{ Data: data, AggregationBits: aggregationBitfield, @@ -199,11 +197,12 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, trace.StringAttribute("blockRoot", fmt.Sprintf("%#x", data.BeaconBlockRoot)), trace.Int64Attribute("justifiedEpoch", int64(data.Source.Epoch)), trace.Int64Attribute("targetEpoch", int64(data.Target.Epoch)), - trace.StringAttribute("aggregationBitfield", fmt.Sprintf("%#x", aggregationBitfield)), ) if postElectra { - span.SetAttributes(trace.StringAttribute("committeeBitfield", fmt.Sprintf("%#x", committeeBits))) + span.SetAttributes(trace.Int64Attribute("attesterIndex", int64(duty.ValidatorIndex))) + span.SetAttributes(trace.Int64Attribute("committeeIndex", int64(duty.CommitteeIndex))) } else { + span.SetAttributes(trace.StringAttribute("aggregationBitfield", fmt.Sprintf("%#x", aggregationBitfield))) span.SetAttributes(trace.Int64Attribute("committeeIndex", int64(data.CommitteeIndex))) } diff --git a/validator/client/attest_test.go b/validator/client/attest_test.go index 68a5b2cce7ec..4ed02f666e6c 100644 --- a/validator/client/attest_test.go +++ b/validator/client/attest_test.go @@ -222,11 +222,11 @@ func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) { gomock.Any(), // epoch ).Times(2).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) - var generatedAttestation *ethpb.AttestationElectra + var generatedAttestation *ethpb.SingleAttestation m.validatorClient.EXPECT().ProposeAttestationElectra( gomock.Any(), // ctx - gomock.AssignableToTypeOf(ðpb.AttestationElectra{}), - ).Do(func(_ context.Context, att *ethpb.AttestationElectra) { + gomock.AssignableToTypeOf(ðpb.SingleAttestation{}), + ).Do(func(_ context.Context, att *ethpb.SingleAttestation) { generatedAttestation = att }).Return(ðpb.AttestResponse{}, nil /* error */) @@ -236,15 +236,15 @@ func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) { aggregationBitfield.SetBitAt(4, true) committeeBits := primitives.NewAttestationCommitteeBits() committeeBits.SetBitAt(5, true) - expectedAttestation := ðpb.AttestationElectra{ + expectedAttestation := ðpb.SingleAttestation{ Data: ðpb.AttestationData{ BeaconBlockRoot: beaconBlockRoot[:], Target: ðpb.Checkpoint{Root: targetRoot[:]}, Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 3}, }, - AggregationBits: aggregationBitfield, - CommitteeBits: committeeBits, - Signature: make([]byte, 96), + AttesterIndex: validatorIndex, + CommitteeId: 5, + Signature: make([]byte, 96), } root, err := signing.ComputeSigningRoot(expectedAttestation.Data, make([]byte, 32)) diff --git a/validator/client/beacon-api/BUILD.bazel b/validator/client/beacon-api/BUILD.bazel index cc25603b9877..c775f846a287 100644 --- a/validator/client/beacon-api/BUILD.bazel +++ b/validator/client/beacon-api/BUILD.bazel @@ -121,6 +121,7 @@ go_test( deps = [ "//api:go_default_library", "//api/server/structs:go_default_library", + "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/rpc/eth/shared/testing:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/validator/client/beacon-api/beacon_api_validator_client.go b/validator/client/beacon-api/beacon_api_validator_client.go index b37f810fedb4..e0f923bbc713 100644 --- a/validator/client/beacon-api/beacon_api_validator_client.go +++ b/validator/client/beacon-api/beacon_api_validator_client.go @@ -154,7 +154,7 @@ func (c *beaconApiValidatorClient) ProposeAttestation(ctx context.Context, in *e }) } -func (c *beaconApiValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) { +func (c *beaconApiValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { ctx, span := trace.StartSpan(ctx, "beacon-api.ProposeAttestationElectra") defer span.End() diff --git a/validator/client/beacon-api/beacon_block_json_helpers.go b/validator/client/beacon-api/beacon_block_json_helpers.go index f5ecf3c73909..c3e5ab552dfb 100644 --- a/validator/client/beacon-api/beacon_block_json_helpers.go +++ b/validator/client/beacon-api/beacon_block_json_helpers.go @@ -51,10 +51,10 @@ func jsonifyAttestations(attestations []*ethpb.Attestation) []*structs.Attestati return jsonAttestations } -func jsonifyAttestationsElectra(attestations []*ethpb.AttestationElectra) []*structs.AttestationElectra { - jsonAttestations := make([]*structs.AttestationElectra, len(attestations)) +func jsonifySingleAttestations(attestations []*ethpb.SingleAttestation) []*structs.SingleAttestation { + jsonAttestations := make([]*structs.SingleAttestation, len(attestations)) for index, attestation := range attestations { - jsonAttestations[index] = jsonifyAttestationElectra(attestation) + jsonAttestations[index] = jsonifySingleAttestation(attestation) } return jsonAttestations } @@ -181,6 +181,15 @@ func jsonifyAttestationElectra(attestation *ethpb.AttestationElectra) *structs.A } } +func jsonifySingleAttestation(attestation *ethpb.SingleAttestation) *structs.SingleAttestation { + return &structs.SingleAttestation{ + CommitteeIndex: uint64ToString(attestation.CommitteeId), + AttesterIndex: uint64ToString(attestation.AttesterIndex), + Data: jsonifyAttestationData(attestation.Data), + Signature: hexutil.Encode(attestation.Signature), + } +} + func jsonifySignedAggregateAndProof(signedAggregateAndProof *ethpb.SignedAggregateAttestationAndProof) *structs.SignedAggregateAttestationAndProof { return &structs.SignedAggregateAttestationAndProof{ Message: &structs.AggregateAttestationAndProof{ diff --git a/validator/client/beacon-api/mock/json_rest_handler_mock.go b/validator/client/beacon-api/mock/json_rest_handler_mock.go index 33722c5bb9e5..1e2e98499cd3 100644 --- a/validator/client/beacon-api/mock/json_rest_handler_mock.go +++ b/validator/client/beacon-api/mock/json_rest_handler_mock.go @@ -58,7 +58,7 @@ func (mr *MockJsonRestHandlerMockRecorder) Get(ctx, endpoint, resp any) *gomock. // Host mocks base method. func (m *MockJsonRestHandler) Host() string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HTTPHost") + ret := m.ctrl.Call(m, "Host") ret0, _ := ret[0].(string) return ret0 } @@ -66,7 +66,7 @@ func (m *MockJsonRestHandler) Host() string { // Host indicates an expected call of Host. func (mr *MockJsonRestHandlerMockRecorder) Host() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HTTPHost", reflect.TypeOf((*MockJsonRestHandler)(nil).Host)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockJsonRestHandler)(nil).Host)) } // HttpClient mocks base method. diff --git a/validator/client/beacon-api/propose_attestation.go b/validator/client/beacon-api/propose_attestation.go index 6dd32975c024..7b78e99b25a8 100644 --- a/validator/client/beacon-api/propose_attestation.go +++ b/validator/client/beacon-api/propose_attestation.go @@ -7,13 +7,14 @@ import ( "net/http" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" ) func (c *beaconApiValidatorClient) proposeAttestation(ctx context.Context, attestation *ethpb.Attestation) (*ethpb.AttestResponse, error) { - if err := validateNilAttestation(attestation); err != nil { + if err := helpers.ValidateNilAttestation(attestation); err != nil { return nil, err } marshalledAttestation, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{attestation})) @@ -58,11 +59,11 @@ func (c *beaconApiValidatorClient) proposeAttestation(ctx context.Context, attes return ðpb.AttestResponse{AttestationDataRoot: attestationDataRoot[:]}, nil } -func (c *beaconApiValidatorClient) proposeAttestationElectra(ctx context.Context, attestation *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) { - if err := validateNilAttestation(attestation); err != nil { +func (c *beaconApiValidatorClient) proposeAttestationElectra(ctx context.Context, attestation *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { + if err := helpers.ValidateNilAttestation(attestation); err != nil { return nil, err } - marshalledAttestation, err := json.Marshal(jsonifyAttestationsElectra([]*ethpb.AttestationElectra{attestation})) + marshalledAttestation, err := json.Marshal(jsonifySingleAttestations([]*ethpb.SingleAttestation{attestation})) if err != nil { return nil, err } @@ -84,28 +85,3 @@ func (c *beaconApiValidatorClient) proposeAttestationElectra(ctx context.Context return ðpb.AttestResponse{AttestationDataRoot: attestationDataRoot[:]}, nil } - -func validateNilAttestation(attestation ethpb.Att) error { - if attestation == nil || attestation.IsNil() { - return errors.New("attestation can't be nil") - } - if attestation.GetData().Source == nil { - return errors.New("attestation's source can't be nil") - } - if attestation.GetData().Target == nil { - return errors.New("attestation's target can't be nil") - } - v := attestation.Version() - if len(attestation.GetAggregationBits()) == 0 { - return errors.New("attestation's bitfield can't be nil") - } - if len(attestation.GetSignature()) == 0 { - return errors.New("attestation signature can't be nil") - } - if v >= version.Electra { - if len(attestation.CommitteeBitsVal().BitIndices()) == 0 { - return errors.New("attestation committee bits can't be nil") - } - } - return nil -} diff --git a/validator/client/beacon-api/propose_attestation_test.go b/validator/client/beacon-api/propose_attestation_test.go index 3ead120bc3a4..250fc2c2f8f7 100644 --- a/validator/client/beacon-api/propose_attestation_test.go +++ b/validator/client/beacon-api/propose_attestation_test.go @@ -8,6 +8,7 @@ import ( "net/http" "testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" @@ -51,7 +52,7 @@ func TestProposeAttestation(t *testing.T) { }, { name: "nil attestation", - expectedErrorMessage: "attestation can't be nil", + expectedErrorMessage: "attestation is nil", }, { name: "nil attestation data", @@ -59,7 +60,7 @@ func TestProposeAttestation(t *testing.T) { AggregationBits: testhelpers.FillByteSlice(4, 74), Signature: testhelpers.FillByteSlice(96, 82), }, - expectedErrorMessage: "attestation can't be nil", + expectedErrorMessage: "attestation is nil", }, { name: "nil source checkpoint", @@ -94,17 +95,6 @@ func TestProposeAttestation(t *testing.T) { }, expectedErrorMessage: "attestation's bitfield can't be nil", }, - { - name: "nil signature", - attestation: ðpb.Attestation{ - AggregationBits: testhelpers.FillByteSlice(4, 74), - Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{}, - Target: ðpb.Checkpoint{}, - }, - }, - expectedErrorMessage: "attestation signature can't be nil", - }, { name: "bad request", attestation: attestation, @@ -120,7 +110,7 @@ func TestProposeAttestation(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) var marshalledAttestations []byte - if validateNilAttestation(test.attestation) == nil { + if helpers.ValidateNilAttestation(test.attestation) == nil { b, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{test.attestation})) require.NoError(t, err) marshalledAttestations = b @@ -181,7 +171,7 @@ func TestProposeAttestationFallBack(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) var marshalledAttestations []byte - if validateNilAttestation(attestation) == nil { + if helpers.ValidateNilAttestation(attestation) == nil { b, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{attestation})) require.NoError(t, err) marshalledAttestations = b @@ -225,8 +215,8 @@ func TestProposeAttestationFallBack(t *testing.T) { } func TestProposeAttestationElectra(t *testing.T) { - attestation := ðpb.AttestationElectra{ - AggregationBits: testhelpers.FillByteSlice(4, 74), + attestation := ðpb.SingleAttestation{ + AttesterIndex: 74, Data: ðpb.AttestationData{ Slot: 75, CommitteeIndex: 76, @@ -240,13 +230,13 @@ func TestProposeAttestationElectra(t *testing.T) { Root: testhelpers.FillByteSlice(32, 81), }, }, - Signature: testhelpers.FillByteSlice(96, 82), - CommitteeBits: testhelpers.FillByteSlice(8, 83), + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, } tests := []struct { name string - attestation *ethpb.AttestationElectra + attestation *ethpb.SingleAttestation expectedErrorMessage string endpointError error endpointCall int @@ -258,86 +248,41 @@ func TestProposeAttestationElectra(t *testing.T) { }, { name: "nil attestation", - expectedErrorMessage: "attestation can't be nil", + expectedErrorMessage: "attestation is nil", }, { name: "nil attestation data", - attestation: ðpb.AttestationElectra{ - AggregationBits: testhelpers.FillByteSlice(4, 74), - Signature: testhelpers.FillByteSlice(96, 82), - CommitteeBits: testhelpers.FillByteSlice(8, 83), + attestation: ðpb.SingleAttestation{ + AttesterIndex: 74, + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, }, - expectedErrorMessage: "attestation can't be nil", + expectedErrorMessage: "attestation is nil", }, { name: "nil source checkpoint", - attestation: ðpb.AttestationElectra{ - AggregationBits: testhelpers.FillByteSlice(4, 74), + attestation: ðpb.SingleAttestation{ + AttesterIndex: 74, Data: ðpb.AttestationData{ Target: ðpb.Checkpoint{}, }, - Signature: testhelpers.FillByteSlice(96, 82), - CommitteeBits: testhelpers.FillByteSlice(8, 83), + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, }, expectedErrorMessage: "attestation's source can't be nil", }, { name: "nil target checkpoint", - attestation: ðpb.AttestationElectra{ - AggregationBits: testhelpers.FillByteSlice(4, 74), + attestation: ðpb.SingleAttestation{ + AttesterIndex: 74, Data: ðpb.AttestationData{ Source: ðpb.Checkpoint{}, }, - Signature: testhelpers.FillByteSlice(96, 82), - CommitteeBits: testhelpers.FillByteSlice(8, 83), + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, }, expectedErrorMessage: "attestation's target can't be nil", }, - { - name: "nil aggregation bits", - attestation: ðpb.AttestationElectra{ - Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{}, - Target: ðpb.Checkpoint{}, - }, - Signature: testhelpers.FillByteSlice(96, 82), - CommitteeBits: testhelpers.FillByteSlice(8, 83), - }, - expectedErrorMessage: "attestation's bitfield can't be nil", - }, - { - name: "nil signature", - attestation: ðpb.AttestationElectra{ - AggregationBits: testhelpers.FillByteSlice(4, 74), - Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{}, - Target: ðpb.Checkpoint{}, - }, - CommitteeBits: testhelpers.FillByteSlice(8, 83), - }, - expectedErrorMessage: "attestation signature can't be nil", - }, - { - name: "nil committee bits", - attestation: ðpb.AttestationElectra{ - AggregationBits: testhelpers.FillByteSlice(4, 74), - Data: ðpb.AttestationData{ - Slot: 75, - CommitteeIndex: 76, - BeaconBlockRoot: testhelpers.FillByteSlice(32, 38), - Source: ðpb.Checkpoint{ - Epoch: 78, - Root: testhelpers.FillByteSlice(32, 79), - }, - Target: ðpb.Checkpoint{ - Epoch: 80, - Root: testhelpers.FillByteSlice(32, 81), - }, - }, - Signature: testhelpers.FillByteSlice(96, 82), - }, - expectedErrorMessage: "attestation committee bits can't be nil", - }, { name: "bad request", attestation: attestation, @@ -353,8 +298,8 @@ func TestProposeAttestationElectra(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) var marshalledAttestations []byte - if validateNilAttestation(test.attestation) == nil { - b, err := json.Marshal(jsonifyAttestationsElectra([]*ethpb.AttestationElectra{test.attestation})) + if helpers.ValidateNilAttestation(test.attestation) == nil { + b, err := json.Marshal(jsonifySingleAttestations([]*ethpb.SingleAttestation{test.attestation})) require.NoError(t, err) marshalledAttestations = b } diff --git a/validator/client/grpc-api/grpc_validator_client.go b/validator/client/grpc-api/grpc_validator_client.go index 63eb07fa4c6d..4e9cdd4d3cd9 100644 --- a/validator/client/grpc-api/grpc_validator_client.go +++ b/validator/client/grpc-api/grpc_validator_client.go @@ -71,7 +71,7 @@ func (c *grpcValidatorClient) ProposeAttestation(ctx context.Context, in *ethpb. return c.beaconNodeValidatorClient.ProposeAttestation(ctx, in) } -func (c *grpcValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) { +func (c *grpcValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { return c.beaconNodeValidatorClient.ProposeAttestationElectra(ctx, in) } diff --git a/validator/client/iface/validator_client.go b/validator/client/iface/validator_client.go index 0f5fc3c18c0a..5ff21ca6486e 100644 --- a/validator/client/iface/validator_client.go +++ b/validator/client/iface/validator_client.go @@ -133,7 +133,7 @@ type ValidatorClient interface { FeeRecipientByPubKey(ctx context.Context, in *ethpb.FeeRecipientByPubKeyRequest) (*ethpb.FeeRecipientByPubKeyResponse, error) AttestationData(ctx context.Context, in *ethpb.AttestationDataRequest) (*ethpb.AttestationData, error) ProposeAttestation(ctx context.Context, in *ethpb.Attestation) (*ethpb.AttestResponse, error) - ProposeAttestationElectra(ctx context.Context, in *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) + ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) SubmitAggregateSelectionProof(ctx context.Context, in *ethpb.AggregateSelectionRequest, index primitives.ValidatorIndex, committeeLength uint64) (*ethpb.AggregateSelectionResponse, error) SubmitAggregateSelectionProofElectra(ctx context.Context, in *ethpb.AggregateSelectionRequest, _ primitives.ValidatorIndex, _ uint64) (*ethpb.AggregateSelectionElectraResponse, error) SubmitSignedAggregateSelectionProof(ctx context.Context, in *ethpb.SignedAggregateSubmitRequest) (*ethpb.SignedAggregateSubmitResponse, error)