From f9232dfde43dae23d0e2f6b18c82609235a88064 Mon Sep 17 00:00:00 2001 From: rkapka Date: Fri, 22 Nov 2024 15:45:32 +0100 Subject: [PATCH 01/17] definitions and gossip --- beacon-chain/core/helpers/attestation.go | 2 +- beacon-chain/p2p/gossip_topic_mappings.go | 4 +- .../p2p/gossip_topic_mappings_test.go | 2 +- beacon-chain/p2p/types/object_mapping.go | 2 +- beacon-chain/sync/validate_aggregate_proof.go | 10 +- .../sync/validate_beacon_attestation.go | 82 ++-- .../validate_beacon_attestation_electra.go | 9 +- proto/prysm/v1alpha1/BUILD.bazel | 1 + proto/prysm/v1alpha1/attestation.go | 110 ++++- proto/prysm/v1alpha1/attestation.pb.go | 381 +++++++++++------- proto/prysm/v1alpha1/attestation.proto | 7 + proto/prysm/v1alpha1/electra.ssz.go | 103 ++++- 12 files changed, 532 insertions(+), 181 deletions(-) diff --git a/beacon-chain/core/helpers/attestation.go b/beacon-chain/core/helpers/attestation.go index 2609bd0e21c0..500bc27cac6c 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/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/sync/validate_aggregate_proof.go b/beacon-chain/sync/validate_aggregate_proof.go index 75dd56095e76..b090962f4a4c 100644 --- a/beacon-chain/sync/validate_aggregate_proof.go +++ b/beacon-chain/sync/validate_aggregate_proof.go @@ -172,10 +172,14 @@ func (s *Service) validateAggregatedAtt(ctx context.Context, signed ethpb.Signed tracing.AnnotateError(span, wrappedErr) return result, err } + committee, err := helpers.BeaconCommitteeFromState(ctx, bs, aggregate.GetData().Slot, committeeIndex) + if err != nil { + return pubsub.ValidationIgnore, err + } - committee, result, err := s.validateBitLength(ctx, bs, aggregate.GetData().Slot, committeeIndex, aggregate.GetAggregationBits()) - if result != pubsub.ValidationAccept { - return result, err + // Verify number of aggregation bits matches the committee size. + if err = helpers.VerifyBitfieldLength(aggregate.GetAggregationBits(), uint64(len(committee))); err != nil { + return pubsub.ValidationReject, err } // Verify validator index is within the beacon committee. diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 11c842e484bf..361ff6d16307 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,6 +70,30 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p if data.Slot == 0 { return pubsub.ValidationIgnore, nil } + + preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + committeeIndex, err := att.GetCommitteeIndex() + if err != nil { + return pubsub.ValidationIgnore, err + } + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) + if err != nil { + return pubsub.ValidationIgnore, err + } + + var singleAtt *eth.SingleAttestation + 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.ToAttestation(committee) + } + // 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{ @@ -147,17 +170,18 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationReject, err } - preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - validationRes, err = s.validateUnaggregatedAttTopic(ctx, att, preState, *msg.Topic) if validationRes != pubsub.ValidationAccept { return validationRes, err } + if singleAtt != nil { + validationRes, err = validateAttestingIndex(ctx, singleAtt, committee) + if validationRes != pubsub.ValidationAccept { + return validationRes, err + } + } + validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, preState) if validationRes != pubsub.ValidationAccept { return validationRes, err @@ -237,7 +261,7 @@ func (s *Service) validateCommitteeIndexAndCount( } count := helpers.SlotCommitteeCount(valCount) 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 } @@ -259,12 +283,15 @@ func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.At 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 + committee, err := helpers.BeaconCommitteeFromState(ctx, bs, a.GetData().Slot, committeeIndex) + if err != nil { + return pubsub.ValidationIgnore, err } + // 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. @@ -281,24 +308,25 @@ func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.At return s.validateWithBatchVerifier(ctx, "attestation", set) } -func (s *Service) validateBitLength( - 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 - } +func validateAttestingIndex(ctx context.Context, a *eth.SingleAttestation, committee []primitives.ValidatorIndex) (pubsub.ValidationResult, error) { + ctx, span := trace.StartSpan(ctx, "sync.validateSingleAttWithState") + 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)`. + attestingIndex := a.GetAttestingIndex() + 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 index 49c6fac2f5a4..dd008107f710 100644 --- a/beacon-chain/sync/validate_beacon_attestation_electra.go +++ b/beacon-chain/sync/validate_beacon_attestation_electra.go @@ -2,7 +2,7 @@ package sync import ( "context" - "fmt" + "errors" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -11,14 +11,13 @@ import ( ) // 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) + + if a.GetData().CommitteeIndex != 0 { + return 0, pubsub.ValidationReject, errors.New("attestation data's committee index must be zero") } committeeIndex, err := a.GetCommitteeIndex() if err != nil { diff --git a/proto/prysm/v1alpha1/BUILD.bazel b/proto/prysm/v1alpha1/BUILD.bazel index 51ec7d961645..b10c87708651 100644 --- a/proto/prysm/v1alpha1/BUILD.bazel +++ b/proto/prysm/v1alpha1/BUILD.bazel @@ -172,6 +172,7 @@ ssz_electra_objs = [ "SignedBeaconBlockElectra", "SignedBlindedBeaconBlockElectra", "SignedConsolidation", + "SingleAttestation", ] ssz_gen_marshal( diff --git a/proto/prysm/v1alpha1/attestation.go b/proto/prysm/v1alpha1/attestation.go index 7cc8a111d558..9340307f4383 100644 --- a/proto/prysm/v1alpha1/attestation.go +++ b/proto/prysm/v1alpha1/attestation.go @@ -21,11 +21,13 @@ type Att interface { Version() int Clone() Att GetAggregationBits() bitfield.Bitlist + GetAttestingIndex() primitives.ValidatorIndex GetData() *AttestationData CommitteeBitsVal() bitfield.Bitfield GetSignature() []byte GetCommitteeIndex() (primitives.CommitteeIndex, error) IsNil() bool + IsSingle() bool } // IndexedAtt defines common functionality for all indexed attestation types. @@ -113,6 +115,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 +} + // Clone -- func (a *Attestation) Clone() Att { return a.Copy() @@ -130,6 +137,11 @@ func (a *Attestation) Copy() *Attestation { } } +// GetAttestingIndex -- +func (*Attestation) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *Attestation) CommitteeBitsVal() bitfield.Bitfield { cb := primitives.NewAttestationCommitteeBits() @@ -155,6 +167,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 +} + // Clone -- func (a *PendingAttestation) Clone() Att { return a.Copy() @@ -173,6 +190,11 @@ func (a *PendingAttestation) Copy() *PendingAttestation { } } +// GetAttestingIndex -- +func (*PendingAttestation) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *PendingAttestation) CommitteeBitsVal() bitfield.Bitfield { return nil @@ -201,6 +223,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 +} + // Clone -- func (a *AttestationElectra) Clone() Att { return a.Copy() @@ -219,6 +246,11 @@ func (a *AttestationElectra) Copy() *AttestationElectra { } } +// GetAttestingIndex -- +func (*AttestationElectra) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *AttestationElectra) CommitteeBitsVal() bitfield.Bitfield { return a.CommitteeBits @@ -232,9 +264,6 @@ func (a *AttestationElectra) GetCommitteeIndex() (primitives.CommitteeIndex, err 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) - } 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)) @@ -242,6 +271,81 @@ func (a *AttestationElectra) GetCommitteeIndex() (primitives.CommitteeIndex, err return primitives.CommitteeIndex(uint64(indices[0])), nil } +// Version -- +func (a *SingleAttestation) Version() int { + return version.Electra +} + +// IsNil -- +func (a *SingleAttestation) IsNil() bool { + return a == nil || a.Data == nil +} + +// 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 +} + +// GetCommitteeIndex -- +func (a *SingleAttestation) GetCommitteeIndex() (primitives.CommitteeIndex, error) { + return a.CommitteeId, nil +} + +func (a *SingleAttestation) ToAttestation(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.Copy(), + Signature: bytesutil.SafeCopyBytes(a.Signature), + CommitteeBits: cb, + } +} + // Version -- func (a *IndexedAttestation) Version() int { return version.Phase0 diff --git a/proto/prysm/v1alpha1/attestation.pb.go b/proto/prysm/v1alpha1/attestation.pb.go index 6b1f970fb1ef..2c3cfc022e16 100755 --- a/proto/prysm/v1alpha1/attestation.pb.go +++ b/proto/prysm/v1alpha1/attestation.pb.go @@ -158,6 +158,77 @@ func (x *AttestationElectra) GetCommitteeBits() github_com_prysmaticlabs_go_bitf return github_com_prysmaticlabs_go_bitfield.Bitvector64(nil) } +type SingleAttestation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommitteeId github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex `protobuf:"varint,1,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"` + AttesterIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=attester_index,json=attesterIndex,proto3" json:"attester_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + Data *AttestationData `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SingleAttestation) Reset() { + *x = SingleAttestation{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SingleAttestation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SingleAttestation) ProtoMessage() {} + +func (x *SingleAttestation) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] + 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 SingleAttestation.ProtoReflect.Descriptor instead. +func (*SingleAttestation) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{2} +} + +func (x *SingleAttestation) GetCommitteeId() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex { + if x != nil { + return x.CommitteeId + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex(0) +} + +func (x *SingleAttestation) GetAttesterIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { + if x != nil { + return x.AttesterIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *SingleAttestation) GetData() *AttestationData { + if x != nil { + return x.Data + } + return nil +} + +func (x *SingleAttestation) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + type AggregateAttestationAndProof struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -171,7 +242,7 @@ type AggregateAttestationAndProof struct { func (x *AggregateAttestationAndProof) Reset() { *x = AggregateAttestationAndProof{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -184,7 +255,7 @@ func (x *AggregateAttestationAndProof) String() string { func (*AggregateAttestationAndProof) ProtoMessage() {} func (x *AggregateAttestationAndProof) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -197,7 +268,7 @@ func (x *AggregateAttestationAndProof) ProtoReflect() protoreflect.Message { // Deprecated: Use AggregateAttestationAndProof.ProtoReflect.Descriptor instead. func (*AggregateAttestationAndProof) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{2} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{3} } func (x *AggregateAttestationAndProof) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { @@ -234,7 +305,7 @@ type AggregateAttestationAndProofElectra struct { func (x *AggregateAttestationAndProofElectra) Reset() { *x = AggregateAttestationAndProofElectra{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -247,7 +318,7 @@ func (x *AggregateAttestationAndProofElectra) String() string { func (*AggregateAttestationAndProofElectra) ProtoMessage() {} func (x *AggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -260,7 +331,7 @@ func (x *AggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Messag // Deprecated: Use AggregateAttestationAndProofElectra.ProtoReflect.Descriptor instead. func (*AggregateAttestationAndProofElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{3} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{4} } func (x *AggregateAttestationAndProofElectra) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { @@ -296,7 +367,7 @@ type SignedAggregateAttestationAndProof struct { func (x *SignedAggregateAttestationAndProof) Reset() { *x = SignedAggregateAttestationAndProof{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -309,7 +380,7 @@ func (x *SignedAggregateAttestationAndProof) String() string { func (*SignedAggregateAttestationAndProof) ProtoMessage() {} func (x *SignedAggregateAttestationAndProof) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -322,7 +393,7 @@ func (x *SignedAggregateAttestationAndProof) ProtoReflect() protoreflect.Message // Deprecated: Use SignedAggregateAttestationAndProof.ProtoReflect.Descriptor instead. func (*SignedAggregateAttestationAndProof) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{4} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{5} } func (x *SignedAggregateAttestationAndProof) GetMessage() *AggregateAttestationAndProof { @@ -351,7 +422,7 @@ type SignedAggregateAttestationAndProofElectra struct { func (x *SignedAggregateAttestationAndProofElectra) Reset() { *x = SignedAggregateAttestationAndProofElectra{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -364,7 +435,7 @@ func (x *SignedAggregateAttestationAndProofElectra) String() string { func (*SignedAggregateAttestationAndProofElectra) ProtoMessage() {} func (x *SignedAggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -377,7 +448,7 @@ func (x *SignedAggregateAttestationAndProofElectra) ProtoReflect() protoreflect. // Deprecated: Use SignedAggregateAttestationAndProofElectra.ProtoReflect.Descriptor instead. func (*SignedAggregateAttestationAndProofElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{5} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{6} } func (x *SignedAggregateAttestationAndProofElectra) GetMessage() *AggregateAttestationAndProofElectra { @@ -409,7 +480,7 @@ type AttestationData struct { func (x *AttestationData) Reset() { *x = AttestationData{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -422,7 +493,7 @@ func (x *AttestationData) String() string { func (*AttestationData) ProtoMessage() {} func (x *AttestationData) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -435,7 +506,7 @@ func (x *AttestationData) ProtoReflect() protoreflect.Message { // Deprecated: Use AttestationData.ProtoReflect.Descriptor instead. func (*AttestationData) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{6} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{7} } func (x *AttestationData) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { @@ -485,7 +556,7 @@ type Checkpoint struct { func (x *Checkpoint) Reset() { *x = Checkpoint{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -498,7 +569,7 @@ func (x *Checkpoint) String() string { func (*Checkpoint) ProtoMessage() {} func (x *Checkpoint) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] + 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 { @@ -511,7 +582,7 @@ func (x *Checkpoint) ProtoReflect() protoreflect.Message { // Deprecated: Use Checkpoint.ProtoReflect.Descriptor instead. func (*Checkpoint) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{7} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{8} } func (x *Checkpoint) GetEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch { @@ -570,106 +641,128 @@ 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, 0x8d, 0x02, 0x0a, 0x1c, 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, 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, 0x40, 0x0a, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 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, 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, 0x9b, 0x02, 0x0a, 0x23, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 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, + 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, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x47, 0x0a, 0x09, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 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, 0x99, 0x01, 0x0a, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, + 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, 0x22, 0x8d, 0x02, 0x0a, 0x1c, 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, 0x12, 0x4d, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, - 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, - 0xa7, 0x01, 0x0a, 0x29, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x54, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, - 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 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, 0x90, 0x03, 0x0a, 0x0f, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x59, 0x0a, - 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, - 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 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, 0x40, 0x0a, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 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, 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, 0x9b, 0x02, 0x0a, 0x23, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, + 0x61, 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, 0x53, 0x6c, - 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x78, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x65, 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, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x39, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x86, 0x01, 0x0a, - 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, - 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, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x04, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x04, 0x72, 0x6f, 0x6f, 0x74, 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, 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, 0x47, 0x0a, + 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 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, 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, 0x99, 0x01, 0x0a, 0x22, 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, 0x12, 0x4d, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x33, 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, 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, 0xa7, 0x01, 0x0a, 0x29, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, + 0x61, 0x12, 0x54, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x3a, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 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, 0x90, 0x03, + 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, + 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x78, 0x0a, 0x0f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 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, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, + 0x82, 0xb5, 0x18, 0x42, 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, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, + 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 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 ( @@ -684,31 +777,33 @@ 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, 8) +var file_proto_prysm_v1alpha1_attestation_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_proto_prysm_v1alpha1_attestation_proto_goTypes = []interface{}{ (*Attestation)(nil), // 0: ethereum.eth.v1alpha1.Attestation (*AttestationElectra)(nil), // 1: ethereum.eth.v1alpha1.AttestationElectra - (*AggregateAttestationAndProof)(nil), // 2: ethereum.eth.v1alpha1.AggregateAttestationAndProof - (*AggregateAttestationAndProofElectra)(nil), // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - (*SignedAggregateAttestationAndProof)(nil), // 4: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof - (*SignedAggregateAttestationAndProofElectra)(nil), // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra - (*AttestationData)(nil), // 6: ethereum.eth.v1alpha1.AttestationData - (*Checkpoint)(nil), // 7: ethereum.eth.v1alpha1.Checkpoint + (*SingleAttestation)(nil), // 2: ethereum.eth.v1alpha1.SingleAttestation + (*AggregateAttestationAndProof)(nil), // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProof + (*AggregateAttestationAndProofElectra)(nil), // 4: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + (*SignedAggregateAttestationAndProof)(nil), // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof + (*SignedAggregateAttestationAndProofElectra)(nil), // 6: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra + (*AttestationData)(nil), // 7: ethereum.eth.v1alpha1.AttestationData + (*Checkpoint)(nil), // 8: ethereum.eth.v1alpha1.Checkpoint } var file_proto_prysm_v1alpha1_attestation_proto_depIdxs = []int32{ - 6, // 0: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 6, // 1: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 0, // 2: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation - 1, // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra - 2, // 4: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof - 3, // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - 7, // 6: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint - 7, // 7: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 7, // 0: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 7, // 1: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 7, // 2: ethereum.eth.v1alpha1.SingleAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 0, // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation + 1, // 4: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra + 3, // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof + 4, // 6: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + 8, // 7: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint + 8, // 8: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint + 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 } func init() { file_proto_prysm_v1alpha1_attestation_proto_init() } @@ -742,7 +837,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregateAttestationAndProof); i { + switch v := v.(*SingleAttestation); i { case 0: return &v.state case 1: @@ -754,7 +849,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregateAttestationAndProofElectra); i { + switch v := v.(*AggregateAttestationAndProof); i { case 0: return &v.state case 1: @@ -766,7 +861,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedAggregateAttestationAndProof); i { + switch v := v.(*AggregateAttestationAndProofElectra); i { case 0: return &v.state case 1: @@ -778,7 +873,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedAggregateAttestationAndProofElectra); i { + switch v := v.(*SignedAggregateAttestationAndProof); i { case 0: return &v.state case 1: @@ -790,7 +885,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttestationData); i { + switch v := v.(*SignedAggregateAttestationAndProofElectra); i { case 0: return &v.state case 1: @@ -802,6 +897,18 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AttestationData); 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[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Checkpoint); i { case 0: return &v.state @@ -820,7 +927,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: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/prysm/v1alpha1/attestation.proto b/proto/prysm/v1alpha1/attestation.proto index a41a3e685fcc..3b30d6aab801 100644 --- a/proto/prysm/v1alpha1/attestation.proto +++ b/proto/prysm/v1alpha1/attestation.proto @@ -49,6 +49,13 @@ message AttestationElectra { bytes committee_bits = 4 [(ethereum.eth.ext.ssz_size) = "committee_bits.size", (ethereum.eth.ext.cast_type) = "committee_bits.type"]; } +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"]; + AttestationData data = 3; + bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; +} + message AggregateAttestationAndProof { // 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"]; diff --git a/proto/prysm/v1alpha1/electra.ssz.go b/proto/prysm/v1alpha1/electra.ssz.go index 16864eaebf0d..05bffda17e4d 100644 --- a/proto/prysm/v1alpha1/electra.ssz.go +++ b/proto/prysm/v1alpha1/electra.ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: bce36d386a65c91018c9a1edaacd2ed0f09cc4dce59fdc5f014fbd9e05bfee77 +// Hash: 678c01efb0c60dfd165322b72151277be12cf3c501117900efa16e90a934b94c package eth import ( @@ -157,6 +157,107 @@ func (a *AttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } +// MarshalSSZ ssz marshals the SingleAttestation object +func (s *SingleAttestation) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SingleAttestation object to a target array +func (s *SingleAttestation) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'CommitteeId' + dst = ssz.MarshalUint64(dst, uint64(s.CommitteeId)) + + // Field (1) 'AttesterIndex' + dst = ssz.MarshalUint64(dst, uint64(s.AttesterIndex)) + + // Field (2) 'Data' + if s.Data == nil { + s.Data = new(AttestationData) + } + if dst, err = s.Data.MarshalSSZTo(dst); err != nil { + return + } + + // Field (3) '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 SingleAttestation object +func (s *SingleAttestation) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 240 { + return ssz.ErrSize + } + + // Field (0) 'CommitteeId' + s.CommitteeId = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'AttesterIndex' + s.AttesterIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + + // Field (2) 'Data' + if s.Data == nil { + s.Data = new(AttestationData) + } + if err = s.Data.UnmarshalSSZ(buf[16:144]); err != nil { + return err + } + + // Field (3) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[144:240])) + } + s.Signature = append(s.Signature, buf[144:240]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SingleAttestation object +func (s *SingleAttestation) SizeSSZ() (size int) { + size = 240 + return +} + +// HashTreeRoot ssz hashes the SingleAttestation object +func (s *SingleAttestation) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SingleAttestation object with a hasher +func (s *SingleAttestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'CommitteeId' + hh.PutUint64(uint64(s.CommitteeId)) + + // Field (1) 'AttesterIndex' + hh.PutUint64(uint64(s.AttesterIndex)) + + // Field (2) 'Data' + if err = s.Data.HashTreeRootWith(hh); err != nil { + return + } + + // Field (3) '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 AggregateAttestationAndProofElectra object func (a *AggregateAttestationAndProofElectra) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(a) From e741580f40e246a2342360007dedfb30c3365458 Mon Sep 17 00:00:00 2001 From: rkapka Date: Fri, 22 Nov 2024 20:12:19 +0100 Subject: [PATCH 02/17] validator --- api/server/structs/conversions.go | 26 ++ api/server/structs/other.go | 7 + beacon-chain/rpc/eth/beacon/handlers_pool.go | 11 +- .../rpc/prysm/v1alpha1/validator/attester.go | 16 +- .../rpc/prysm/v1alpha1/validator/server.go | 73 ++-- beacon-chain/rpc/service.go | 73 ++-- .../sync/validate_beacon_attestation.go | 1 + proto/prysm/v1alpha1/validator.pb.go | 408 +++++++++--------- proto/prysm/v1alpha1/validator.proto | 2 +- validator/client/attest.go | 54 ++- .../beacon-api/beacon_api_validator_client.go | 2 +- .../beacon-api/beacon_block_json_helpers.go | 17 + .../client/beacon-api/propose_attestation.go | 4 +- .../client/grpc-api/grpc_validator_client.go | 2 +- validator/client/iface/validator_client.go | 2 +- 15 files changed, 382 insertions(+), 316 deletions(-) diff --git a/api/server/structs/conversions.go b/api/server/structs/conversions.go index 9ed1f50e4e67..64c154ba99d2 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/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index f522e659b5a7..903db47c2672 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -277,8 +277,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") @@ -288,7 +291,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 { @@ -308,6 +311,7 @@ func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMes validAttestations = append(validAttestations, att) } + // TODO: Send single or not? for i, att := range validAttestations { // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node // of a received unaggregated attestation. @@ -338,6 +342,7 @@ func (s *Server) handleAttestationsElectra(ctx context.Context, data json.RawMes continue } + // TODO: convert to AttestationElectra if corehelpers.IsAggregated(att) { if err = s.AttestationsPool.SaveAggregatedAttestation(att); err != nil { log.WithError(err).Error("could not save aggregated attestation") diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go index 5dceed5703b5..68dbf4d822e6 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -62,7 +62,7 @@ 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() @@ -78,8 +78,17 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.Atte go func() { ctx = trace.NewContext(context.Background(), trace.FromContext(ctx)) - attCopy := att.Copy() - if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil { + preState, err := vs.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target) + if err != nil { + log.WithError(err).Error("Could not get target state for proposed attestation") + return + } + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.Data.Slot, committeeIndex) + if err != nil { + log.WithError(err).Error("Could not get committee for proposed attestation") + return + } + if err := vs.AttPool.SaveUnaggregatedAttestation(att.ToAttestation(committee)); err != nil { log.WithError(err).Error("Could not save unaggregated attestation") return } @@ -146,6 +155,7 @@ func (vs *Server) proposeAtt(ctx context.Context, att ethpb.Att, committee primi return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err) } + // TODO: Send single or not? // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node // of a received unaggregated attestation. vs.OperationNotifier.OperationFeed().Send(&feed.Event{ diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go index 34256c733a5c..7c8e3bb94114 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go @@ -42,42 +42,43 @@ 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 - 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 + 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 4a56c0d4162e..53cfe1240a89 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -231,42 +231,43 @@ func NewService(ctx context.Context, cfg *Config) *Service { OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, } validatorServer := &validatorv1alpha1.Server{ - Ctx: s.ctx, - 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, + 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/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 361ff6d16307..8fffa74d4111 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -94,6 +94,7 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p att = singleAtt.ToAttestation(committee) } + // TODO: Send single or not? // 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{ 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/validator/client/attest.go b/validator/client/attest.go index 0c2f92a83cc6..13c0b61a3d21 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,11 @@ 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("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/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..dd9d69794cd9 100644 --- a/validator/client/beacon-api/beacon_block_json_helpers.go +++ b/validator/client/beacon-api/beacon_block_json_helpers.go @@ -59,6 +59,14 @@ func jsonifyAttestationsElectra(attestations []*ethpb.AttestationElectra) []*str return jsonAttestations } +func jsonifySingleAttestations(attestations []*ethpb.SingleAttestation) []*structs.SingleAttestation { + jsonAttestations := make([]*structs.SingleAttestation, len(attestations)) + for index, attestation := range attestations { + jsonAttestations[index] = jsonifySingleAttestation(attestation) + } + return jsonAttestations +} + func jsonifyAttesterSlashings(attesterSlashings []*ethpb.AttesterSlashing) []*structs.AttesterSlashing { jsonAttesterSlashings := make([]*structs.AttesterSlashing, len(attesterSlashings)) for index, attesterSlashing := range attesterSlashings { @@ -181,6 +189,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/propose_attestation.go b/validator/client/beacon-api/propose_attestation.go index 6dd32975c024..325ecd91a4fb 100644 --- a/validator/client/beacon-api/propose_attestation.go +++ b/validator/client/beacon-api/propose_attestation.go @@ -58,11 +58,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) { +func (c *beaconApiValidatorClient) proposeAttestationElectra(ctx context.Context, attestation *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { if err := 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 } 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) From df5338a6b62a9aded065551266f2f155134a010a Mon Sep 17 00:00:00 2001 From: rkapka Date: Mon, 25 Nov 2024 19:44:19 +0100 Subject: [PATCH 03/17] broadcast --- beacon-chain/rpc/endpoints.go | 1 + beacon-chain/rpc/eth/beacon/handlers_pool.go | 12 ++++- beacon-chain/rpc/eth/beacon/server.go | 1 + .../rpc/prysm/v1alpha1/validator/attester.go | 47 ++++++++++++------- .../sync/validate_beacon_attestation.go | 1 - 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/beacon-chain/rpc/endpoints.go b/beacon-chain/rpc/endpoints.go index 1b32e2142ec0..0055dbbf5d8a 100644 --- a/beacon-chain/rpc/endpoints.go +++ b/beacon-chain/rpc/endpoints.go @@ -497,6 +497,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 903db47c2672..32945189be46 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -311,8 +311,16 @@ func (s *Server) handleAttestationsElectra( validAttestations = append(validAttestations, att) } - // TODO: Send single or not? 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. @@ -320,7 +328,7 @@ func (s *Server) handleAttestationsElectra( s.OperationNotifier.OperationFeed().Send(&feed.Event{ Type: operation.UnaggregatedAttReceived, Data: &operation.UnAggregatedAttReceivedData{ - Attestation: att, + Attestation: att.ToAttestation(committee), }, }) } diff --git a/beacon-chain/rpc/eth/beacon/server.go b/beacon-chain/rpc/eth/beacon/server.go index 878f533f908d..7b3a68744ac7 100644 --- a/beacon-chain/rpc/eth/beacon/server.go +++ b/beacon-chain/rpc/eth/beacon/server.go @@ -48,4 +48,5 @@ type Server struct { BLSChangesPool blstoexec.PoolManager ForkchoiceFetcher blockchain.ForkchoiceFetcher CoreService *core.Service + AttestationStateFetcher blockchain.AttestationStateFetcher } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go index 68dbf4d822e6..becd8f69a2e5 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -12,6 +12,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" @@ -44,7 +45,8 @@ 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) + // TODO: is there a cleaner way than to pass nil here? + resp, err := vs.proposeAtt(ctx, att, nil, att.GetData().CommitteeIndex) if err != nil { return nil, err } @@ -71,23 +73,22 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.Sing return nil, err } - resp, err := vs.proposeAtt(ctx, att, committeeIndex) + targetState, err := vs.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target) + if err != nil { + return nil, status.Error(codes.Internal, "Could not get target state for proposed attestation") + } + committee, err := helpers.BeaconCommitteeFromState(ctx, targetState, att.Data.Slot, committeeIndex) + if err != nil { + return nil, status.Error(codes.Internal, "Could not get committee for proposed attestation") + } + + resp, err := vs.proposeAtt(ctx, att, committee, committeeIndex) if err != nil { return nil, err } go func() { ctx = trace.NewContext(context.Background(), trace.FromContext(ctx)) - preState, err := vs.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target) - if err != nil { - log.WithError(err).Error("Could not get target state for proposed attestation") - return - } - committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.Data.Slot, committeeIndex) - if err != nil { - log.WithError(err).Error("Could not get committee for proposed attestation") - return - } if err := vs.AttPool.SaveUnaggregatedAttestation(att.ToAttestation(committee)); err != nil { log.WithError(err).Error("Could not save unaggregated attestation") return @@ -145,7 +146,12 @@ 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, + committeeIndex primitives.CommitteeIndex, +) (*ethpb.AttestResponse, error) { if _, err := bls.SignatureFromBytes(att.GetSignature()); err != nil { return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature") } @@ -155,7 +161,16 @@ func (vs *Server) proposeAtt(ctx context.Context, att ethpb.Att, committee primi return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err) } - // TODO: Send single or not? + 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.ToAttestation(committee) + } + // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node // of a received unaggregated attestation. vs.OperationNotifier.OperationFeed().Send(&feed.Event{ @@ -171,10 +186,10 @@ 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 { + if err := vs.P2P.BroadcastAttestation(ctx, subnet, singleAtt); err != nil { return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) } diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 8fffa74d4111..361ff6d16307 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -94,7 +94,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p att = singleAtt.ToAttestation(committee) } - // TODO: Send single or not? // 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{ From c8ecac2ff64bf162e3f216b6b74539a2ddb438ef Mon Sep 17 00:00:00 2001 From: rkapka Date: Tue, 26 Nov 2024 17:19:33 +0100 Subject: [PATCH 04/17] broadcast the correct att depending on version --- beacon-chain/rpc/prysm/v1alpha1/validator/attester.go | 10 ++++++++-- beacon-chain/sync/validate_beacon_attestation.go | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go index becd8f69a2e5..ed5e40255c32 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -189,8 +189,14 @@ func (vs *Server) proposeAtt( subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committeeIndex, att.GetData().Slot) // Broadcast the new attestation to the network. - if err := vs.P2P.BroadcastAttestation(ctx, subnet, singleAtt); err != nil { - return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) + if singleAtt != nil { + if err := vs.P2P.BroadcastAttestation(ctx, subnet, singleAtt); err != nil { + return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) + } + } else { + if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil { + return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) + } } return ðpb.AttestResponse{ diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 361ff6d16307..2cb32786ff82 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -309,7 +309,7 @@ func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.At } func validateAttestingIndex(ctx context.Context, a *eth.SingleAttestation, committee []primitives.ValidatorIndex) (pubsub.ValidationResult, error) { - ctx, span := trace.StartSpan(ctx, "sync.validateSingleAttWithState") + _, span := trace.StartSpan(ctx, "sync.validateAttestingIndex") defer span.End() // _[REJECT]_ The attester is a member of the committee -- i.e. From 4215a952837c476c57c72e27b6b9a9907a32bc7f Mon Sep 17 00:00:00 2001 From: rkapka Date: Wed, 27 Nov 2024 19:05:57 +0100 Subject: [PATCH 05/17] small updates --- beacon-chain/rpc/eth/beacon/handlers_pool.go | 8 ++--- .../rpc/prysm/v1alpha1/validator/attester.go | 32 +++++++++---------- .../sync/validate_beacon_attestation.go | 4 ++- proto/prysm/v1alpha1/attestation.go | 3 +- validator/client/attest.go | 1 + 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index 7ef0c6611d6c..ca6a3c318d51 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -325,7 +325,7 @@ func (s *Server) handleAttestationsElectra( s.OperationNotifier.OperationFeed().Send(&feed.Event{ Type: operation.UnaggregatedAttReceived, Data: &operation.UnAggregatedAttReceivedData{ - Attestation: att.ToAttestation(committee), + Attestation: att.ToAttestationElectra(committee), }, }) } @@ -347,13 +347,13 @@ func (s *Server) handleAttestationsElectra( continue } - // TODO: convert to AttestationElectra + electraAtt := att.ToAttestationElectra(committee) if corehelpers.IsAggregated(att) { - if err = s.AttestationsPool.SaveAggregatedAttestation(att); err != nil { + if err = s.AttestationsPool.SaveAggregatedAttestation(electraAtt); err != nil { log.WithError(err).Error("could not save aggregated attestation") } } else { - if err = s.AttestationsPool.SaveUnaggregatedAttestation(att); err != nil { + if err = s.AttestationsPool.SaveUnaggregatedAttestation(electraAtt); err != nil { log.WithError(err).Error("could not save unaggregated attestation") } } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go index ed5e40255c32..782dc2f8eb03 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -45,7 +45,6 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestation") defer span.End() - // TODO: is there a cleaner way than to pass nil here? resp, err := vs.proposeAtt(ctx, att, nil, att.GetData().CommitteeIndex) if err != nil { return nil, err @@ -68,18 +67,17 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.Sing 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") } - - targetState, err := vs.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target) + committeeIndex, err := att.GetCommitteeIndex() if err != nil { - return nil, status.Error(codes.Internal, "Could not get target state for proposed attestation") + return nil, status.Error(codes.Internal, "Could not get committee index") } committee, err := helpers.BeaconCommitteeFromState(ctx, targetState, att.Data.Slot, committeeIndex) if err != nil { - return nil, status.Error(codes.Internal, "Could not get committee for proposed attestation") + return nil, status.Error(codes.Internal, "Could not get committee") } resp, err := vs.proposeAtt(ctx, att, committee, committeeIndex) @@ -89,7 +87,7 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.Sing go func() { ctx = trace.NewContext(context.Background(), trace.FromContext(ctx)) - if err := vs.AttPool.SaveUnaggregatedAttestation(att.ToAttestation(committee)); err != nil { + if err := vs.AttPool.SaveUnaggregatedAttestation(att.ToAttestationElectra(committee)); err != nil { log.WithError(err).Error("Could not save unaggregated attestation") return } @@ -149,7 +147,7 @@ func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.Comm func (vs *Server) proposeAtt( ctx context.Context, att ethpb.Att, - committee []primitives.ValidatorIndex, + committee []primitives.ValidatorIndex, // required post-Electra committeeIndex primitives.CommitteeIndex, ) (*ethpb.AttestResponse, error) { if _, err := bls.SignatureFromBytes(att.GetSignature()); err != nil { @@ -158,7 +156,7 @@ func (vs *Server) proposeAtt( 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 @@ -168,7 +166,7 @@ func (vs *Server) proposeAtt( if !ok { return nil, status.Errorf(codes.Internal, "Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, att) } - att = singleAtt.ToAttestation(committee) + att = singleAtt.ToAttestationElectra(committee) } // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node @@ -189,14 +187,14 @@ func (vs *Server) proposeAtt( subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committeeIndex, att.GetData().Slot) // Broadcast the new attestation to the network. + var attToBroadcast ethpb.Att if singleAtt != nil { - if err := vs.P2P.BroadcastAttestation(ctx, subnet, singleAtt); err != nil { - return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) - } + attToBroadcast = singleAtt } else { - if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil { - return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) - } + attToBroadcast = att + } + if err := vs.P2P.BroadcastAttestation(ctx, subnet, attToBroadcast); err != nil { + return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err) } return ðpb.AttestResponse{ diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 2cb32786ff82..0ebf8589890c 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -78,10 +78,12 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p } committeeIndex, err := att.GetCommitteeIndex() if err != nil { + tracing.AnnotateError(span, err) return pubsub.ValidationIgnore, err } committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) if err != nil { + tracing.AnnotateError(span, err) return pubsub.ValidationIgnore, err } @@ -91,7 +93,7 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p if !ok { return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, att) } - att = singleAtt.ToAttestation(committee) + att = singleAtt.ToAttestationElectra(committee) } // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node diff --git a/proto/prysm/v1alpha1/attestation.go b/proto/prysm/v1alpha1/attestation.go index 9340307f4383..d2c94d8321ee 100644 --- a/proto/prysm/v1alpha1/attestation.go +++ b/proto/prysm/v1alpha1/attestation.go @@ -326,7 +326,8 @@ func (a *SingleAttestation) GetCommitteeIndex() (primitives.CommitteeIndex, erro return a.CommitteeId, nil } -func (a *SingleAttestation) ToAttestation(committee []primitives.ValidatorIndex) *AttestationElectra { +// ToAttestationElectra converts the attestation to an AttestationElectra. +func (a *SingleAttestation) ToAttestationElectra(committee []primitives.ValidatorIndex) *AttestationElectra { cb := primitives.NewAttestationCommitteeBits() cb.SetBitAt(uint64(a.CommitteeId), true) diff --git a/validator/client/attest.go b/validator/client/attest.go index 13c0b61a3d21..1ec917aa4736 100644 --- a/validator/client/attest.go +++ b/validator/client/attest.go @@ -199,6 +199,7 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, trace.Int64Attribute("targetEpoch", int64(data.Target.Epoch)), ) if postElectra { + 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))) From fd296d971ad552945aa086887c3708eb8ba0a44a Mon Sep 17 00:00:00 2001 From: rkapka Date: Fri, 29 Nov 2024 15:53:34 +0100 Subject: [PATCH 06/17] don't check bits after Electra --- validator/client/beacon-api/propose_attestation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator/client/beacon-api/propose_attestation.go b/validator/client/beacon-api/propose_attestation.go index 325ecd91a4fb..1b419c094496 100644 --- a/validator/client/beacon-api/propose_attestation.go +++ b/validator/client/beacon-api/propose_attestation.go @@ -96,7 +96,7 @@ func validateNilAttestation(attestation ethpb.Att) error { return errors.New("attestation's target can't be nil") } v := attestation.Version() - if len(attestation.GetAggregationBits()) == 0 { + if !attestation.IsSingle() && len(attestation.GetAggregationBits()) == 0 { return errors.New("attestation's bitfield can't be nil") } if len(attestation.GetSignature()) == 0 { From 67e92e0c90682ebe7d8b11cbad674061203524c6 Mon Sep 17 00:00:00 2001 From: rkapka Date: Fri, 29 Nov 2024 16:07:14 +0100 Subject: [PATCH 07/17] nitpick --- beacon-chain/rpc/eth/beacon/handlers_pool.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index ca6a3c318d51..d183ab8c0775 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -347,13 +347,12 @@ func (s *Server) handleAttestationsElectra( continue } - electraAtt := att.ToAttestationElectra(committee) if corehelpers.IsAggregated(att) { - if err = s.AttestationsPool.SaveAggregatedAttestation(electraAtt); err != nil { + if err = s.AttestationsPool.SaveAggregatedAttestation(att.ToAttestationElectra(committee)); err != nil { log.WithError(err).Error("could not save aggregated attestation") } } else { - if err = s.AttestationsPool.SaveUnaggregatedAttestation(electraAtt); err != nil { + if err = s.AttestationsPool.SaveUnaggregatedAttestation(att.ToAttestationElectra(committee)); err != nil { log.WithError(err).Error("could not save unaggregated attestation") } } From 9d70083b8c2b986280818ffb70039c6bc583a0c2 Mon Sep 17 00:00:00 2001 From: rkapka Date: Tue, 10 Dec 2024 16:59:53 -0500 Subject: [PATCH 08/17] tests --- beacon-chain/core/helpers/attestation_test.go | 10 ++ .../core/helpers/beacon_committee_test.go | 8 ++ .../rpc/eth/beacon/handlers_pool_test.go | 31 +++-- .../prysm/v1alpha1/validator/attester_test.go | 76 ++--------- beacon-chain/sync/decode_pubsub_test.go | 2 +- .../sync/validate_aggregate_proof_test.go | 7 - ...alidate_beacon_attestation_electra_test.go | 24 +--- testing/mock/beacon_service_mock.go | 4 +- testing/mock/beacon_validator_client_mock.go | 125 +++++++++++++++++- testing/mock/beacon_validator_server_mock.go | 2 +- .../validator-mock/validator_client_mock.go | 21 +-- validator/client/attest_test.go | 14 +- validator/client/beacon-api/BUILD.bazel | 1 + .../beacon-api/beacon_block_json_helpers.go | 8 -- .../beacon-api/mock/json_rest_handler_mock.go | 4 +- .../client/beacon-api/propose_attestation.go | 30 +---- .../beacon-api/propose_attestation_test.go | 107 ++++----------- 17 files changed, 217 insertions(+), 257 deletions(-) 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..628ae63adf45 100644 --- a/beacon-chain/core/helpers/beacon_committee_test.go +++ b/beacon-chain/core/helpers/beacon_committee_test.go @@ -97,6 +97,14 @@ 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_WrongLength(t *testing.T) { + helpers.ClearCache() + + bf := bitfield.Bitlist{0xFF, 0x01} + committeeSize := uint64(4) + require.ErrorContains(t, "wanted participants bitfield length 4, got: 8", helpers.VerifyBitfieldLength(bf, committeeSize)) +} + func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) { helpers.ClearCache() 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/prysm/v1alpha1/validator/attester_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go index e293d09f2574..34b2d574d3b1 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/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/validate_aggregate_proof_test.go b/beacon-chain/sync/validate_aggregate_proof_test.go index 6376e3f42d6e..b3e49fc8ac90 100644 --- a/beacon-chain/sync/validate_aggregate_proof_test.go +++ b/beacon-chain/sync/validate_aggregate_proof_test.go @@ -94,13 +94,6 @@ 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) require.ErrorContains(t, "committee index 10000 > 2", err) diff --git a/beacon-chain/sync/validate_beacon_attestation_electra_test.go b/beacon-chain/sync/validate_beacon_attestation_electra_test.go index 81c8e2e9dff9..332929ad056e 100644 --- a/beacon-chain/sync/validate_beacon_attestation_electra_test.go +++ b/beacon-chain/sync/validate_beacon_attestation_electra_test.go @@ -15,31 +15,13 @@ 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}) + ci, res, err := validateCommitteeIndexElectra(ctx, ðpb.SingleAttestation{Data: ðpb.AttestationData{}, CommitteeId: 1}) 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}) + t.Run("non-zero committee index in att data", func(t *testing.T) { + _, res, err := validateCommitteeIndexElectra(ctx, ðpb.SingleAttestation{Data: ðpb.AttestationData{CommitteeIndex: 1}}) assert.NotNil(t, err) assert.Equal(t, pubsub.ValidationReject, res) }) 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_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_block_json_helpers.go b/validator/client/beacon-api/beacon_block_json_helpers.go index dd9d69794cd9..c3e5ab552dfb 100644 --- a/validator/client/beacon-api/beacon_block_json_helpers.go +++ b/validator/client/beacon-api/beacon_block_json_helpers.go @@ -51,14 +51,6 @@ func jsonifyAttestations(attestations []*ethpb.Attestation) []*structs.Attestati return jsonAttestations } -func jsonifyAttestationsElectra(attestations []*ethpb.AttestationElectra) []*structs.AttestationElectra { - jsonAttestations := make([]*structs.AttestationElectra, len(attestations)) - for index, attestation := range attestations { - jsonAttestations[index] = jsonifyAttestationElectra(attestation) - } - return jsonAttestations -} - func jsonifySingleAttestations(attestations []*ethpb.SingleAttestation) []*structs.SingleAttestation { jsonAttestations := make([]*structs.SingleAttestation, len(attestations)) for index, attestation := range attestations { 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 1b419c094496..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})) @@ -59,7 +60,7 @@ func (c *beaconApiValidatorClient) proposeAttestation(ctx context.Context, attes } func (c *beaconApiValidatorClient) proposeAttestationElectra(ctx context.Context, attestation *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { - if err := validateNilAttestation(attestation); err != nil { + if err := helpers.ValidateNilAttestation(attestation); err != nil { return nil, err } marshalledAttestation, err := json.Marshal(jsonifySingleAttestations([]*ethpb.SingleAttestation{attestation})) @@ -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 !attestation.IsSingle() && 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 } From b04ccbe71ba027bf707ebaf3e94fa51434a2889a Mon Sep 17 00:00:00 2001 From: rkapka Date: Wed, 11 Dec 2024 12:23:02 -0500 Subject: [PATCH 09/17] changelog <3 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03eae5766d80..036971b6ec59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve - Added a Prometheus error counter metric for HTTP requests to track beacon node requests. - Added a Prometheus error counter metric for SSE requests. - Save light client updates and bootstraps in DB. +- Separate type for unaggregated network attestations. [PR](https://github.com/prysmaticlabs/prysm/pull/14659) ### Changed From d3387b30681b16d5072b6b7e57e142f2c56a718c Mon Sep 17 00:00:00 2001 From: rkapka Date: Fri, 13 Dec 2024 13:30:13 -0500 Subject: [PATCH 10/17] review --- .../sync/validate_beacon_attestation.go | 88 +++++++++---------- proto/prysm/v1alpha1/attestation.go | 4 +- 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 0ebf8589890c..c613b5d30a45 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -71,40 +71,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationIgnore, nil } - preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - committeeIndex, err := att.GetCommitteeIndex() - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - - var singleAtt *eth.SingleAttestation - 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) - } - - // 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. if err := helpers.ValidateAttestationTime(data.Slot, s.cfg.clock.GenesisTime(), @@ -116,8 +82,6 @@ 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())) @@ -140,6 +104,48 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p } } + if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { + tracing.AnnotateError(span, blockchain.ErrNotDescendantOfFinalized) + return pubsub.ValidationIgnore, blockchain.ErrNotDescendantOfFinalized + } + + if err = s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { + tracing.AnnotateError(span, err) + attBadLmdConsistencyCount.Inc() + return pubsub.ValidationReject, err + } + + preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + + var singleAtt *eth.SingleAttestation + 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) + } + + // 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, + }, + }) + + 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) { @@ -162,16 +168,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationIgnore, nil } - if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { - tracing.AnnotateError(span, blockchain.ErrNotDescendantOfFinalized) - return pubsub.ValidationIgnore, blockchain.ErrNotDescendantOfFinalized - } - if err := s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { - tracing.AnnotateError(span, err) - attBadLmdConsistencyCount.Inc() - return pubsub.ValidationReject, err - } - validationRes, err = s.validateUnaggregatedAttTopic(ctx, att, preState, *msg.Topic) if validationRes != pubsub.ValidationAccept { return validationRes, err diff --git a/proto/prysm/v1alpha1/attestation.go b/proto/prysm/v1alpha1/attestation.go index d2c94d8321ee..4cef23af85c6 100644 --- a/proto/prysm/v1alpha1/attestation.go +++ b/proto/prysm/v1alpha1/attestation.go @@ -341,8 +341,8 @@ func (a *SingleAttestation) ToAttestationElectra(committee []primitives.Validato return &AttestationElectra{ AggregationBits: ab, - Data: a.Data.Copy(), - Signature: bytesutil.SafeCopyBytes(a.Signature), + Data: a.Data, + Signature: a.Signature, CommitteeBits: cb, } } From a9f3844479a9eb3bd84962b689102fe69d6232c5 Mon Sep 17 00:00:00 2001 From: rkapka Date: Wed, 18 Dec 2024 09:57:34 +0100 Subject: [PATCH 11/17] more review --- .../core/helpers/beacon_committee_test.go | 8 --- beacon-chain/sync/validate_aggregate_proof.go | 10 ++-- .../sync/validate_aggregate_proof_test.go | 7 +++ .../sync/validate_beacon_attestation.go | 53 ++++++++++++------- 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/beacon-chain/core/helpers/beacon_committee_test.go b/beacon-chain/core/helpers/beacon_committee_test.go index 628ae63adf45..007685617e22 100644 --- a/beacon-chain/core/helpers/beacon_committee_test.go +++ b/beacon-chain/core/helpers/beacon_committee_test.go @@ -97,14 +97,6 @@ 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_WrongLength(t *testing.T) { - helpers.ClearCache() - - bf := bitfield.Bitlist{0xFF, 0x01} - committeeSize := uint64(4) - require.ErrorContains(t, "wanted participants bitfield length 4, got: 8", helpers.VerifyBitfieldLength(bf, committeeSize)) -} - func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) { helpers.ClearCache() diff --git a/beacon-chain/sync/validate_aggregate_proof.go b/beacon-chain/sync/validate_aggregate_proof.go index 96b0552df521..614f3aca85ed 100644 --- a/beacon-chain/sync/validate_aggregate_proof.go +++ b/beacon-chain/sync/validate_aggregate_proof.go @@ -175,14 +175,10 @@ func (s *Service) validateAggregatedAtt(ctx context.Context, signed ethpb.Signed tracing.AnnotateError(span, wrappedErr) return result, err } - committee, err := helpers.BeaconCommitteeFromState(ctx, bs, aggregate.GetData().Slot, committeeIndex) - if err != nil { - return pubsub.ValidationIgnore, err - } - // Verify number of aggregation bits matches the committee size. - if err = helpers.VerifyBitfieldLength(aggregate.GetAggregationBits(), uint64(len(committee))); err != nil { - return pubsub.ValidationReject, err + committee, result, err := s.validateBitLength(ctx, bs, aggregate.GetData().Slot, committeeIndex, aggregate.GetAggregationBits()) + if result != pubsub.ValidationAccept { + return result, 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 b3e49fc8ac90..6376e3f42d6e 100644 --- a/beacon-chain/sync/validate_aggregate_proof_test.go +++ b/beacon-chain/sync/validate_aggregate_proof_test.go @@ -94,6 +94,13 @@ 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) require.ErrorContains(t, "committee index 10000 > 2", err) diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index c613b5d30a45..12bafa88ab9e 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -9,6 +9,7 @@ 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" @@ -104,17 +105,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p } } - if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { - tracing.AnnotateError(span, blockchain.ErrNotDescendantOfFinalized) - return pubsub.ValidationIgnore, blockchain.ErrNotDescendantOfFinalized - } - - if err = s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { - tracing.AnnotateError(span, err) - attBadLmdConsistencyCount.Inc() - return pubsub.ValidationReject, err - } - preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) if err != nil { tracing.AnnotateError(span, err) @@ -168,6 +158,17 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationIgnore, nil } + if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { + tracing.AnnotateError(span, blockchain.ErrNotDescendantOfFinalized) + return pubsub.ValidationIgnore, blockchain.ErrNotDescendantOfFinalized + } + + if err = s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { + tracing.AnnotateError(span, err) + attBadLmdConsistencyCount.Inc() + return pubsub.ValidationReject, err + } + validationRes, err = s.validateUnaggregatedAttTopic(ctx, att, preState, *msg.Topic) if validationRes != pubsub.ValidationAccept { return validationRes, err @@ -281,14 +282,10 @@ func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.At if err != nil { return pubsub.ValidationIgnore, err } - committee, err := helpers.BeaconCommitteeFromState(ctx, bs, a.GetData().Slot, committeeIndex) - if err != nil { - return pubsub.ValidationIgnore, err - } - // Verify number of aggregation bits matches the committee size. - if err = helpers.VerifyBitfieldLength(a.GetAggregationBits(), uint64(len(committee))); err != nil { - return pubsub.ValidationReject, 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) @@ -306,6 +303,26 @@ func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.At return s.validateWithBatchVerifier(ctx, "attestation", set) } +func (s *Service) validateBitLength( + 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 + } + + // Verify number of aggregation bits matches the committee size. + if err := helpers.VerifyBitfieldLength(aggregationBits, uint64(len(committee))); err != nil { + return nil, pubsub.ValidationReject, err + } + + return committee, pubsub.ValidationAccept, nil +} + func validateAttestingIndex(ctx context.Context, a *eth.SingleAttestation, committee []primitives.ValidatorIndex) (pubsub.ValidationResult, error) { _, span := trace.StartSpan(ctx, "sync.validateAttestingIndex") defer span.End() From abf7e6d8de3365fa060a759cdbeab931f148b649 Mon Sep 17 00:00:00 2001 From: rkapka Date: Mon, 23 Dec 2024 11:41:34 +0100 Subject: [PATCH 12/17] review yet again --- .../sync/validate_beacon_attestation.go | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 12bafa88ab9e..58495a8d31d6 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -105,35 +105,6 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p } } - preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - - var singleAtt *eth.SingleAttestation - 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) - } - - // 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, - }, - }) - 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. @@ -169,6 +140,26 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationReject, err } + preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + + var singleAtt *eth.SingleAttestation + 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.validateUnaggregatedAttTopic(ctx, att, preState, *msg.Topic) if validationRes != pubsub.ValidationAccept { return validationRes, err @@ -215,6 +206,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 From 023c99ddf4492d7c6af288411550cf49bb9453ea Mon Sep 17 00:00:00 2001 From: rkapka Date: Mon, 23 Dec 2024 17:45:18 +0100 Subject: [PATCH 13/17] try a different design --- beacon-chain/rpc/eth/beacon/handlers_pool.go | 6 +- beacon-chain/rpc/eth/validator/handlers.go | 6 +- .../rpc/prysm/v1alpha1/validator/attester.go | 5 +- beacon-chain/sync/BUILD.bazel | 2 - .../sync/pending_attestations_queue.go | 12 +- .../sync/subscriber_beacon_attestation.go | 5 +- beacon-chain/sync/validate_aggregate_proof.go | 15 +- .../sync/validate_beacon_attestation.go | 141 +++---- .../validate_beacon_attestation_electra.go | 27 -- ...alidate_beacon_attestation_electra_test.go | 28 -- proto/prysm/v1alpha1/BUILD.bazel | 4 +- proto/prysm/v1alpha1/attestation.go | 64 ++- proto/prysm/v1alpha1/attestation.pb.go | 373 +++++++++++++----- proto/prysm/v1alpha1/attestation.proto | 19 + proto/prysm/v1alpha1/electra.ssz.go | 177 ++++++++- 15 files changed, 604 insertions(+), 280 deletions(-) delete mode 100644 beacon-chain/sync/validate_beacon_attestation_electra.go delete mode 100644 beacon-chain/sync/validate_beacon_attestation_electra_test.go diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index d183ab8c0775..f27af61267d9 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -336,11 +336,7 @@ func (s *Server) handleAttestationsElectra( 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)) diff --git a/beacon-chain/rpc/eth/validator/handlers.go b/beacon-chain/rpc/eth/validator/handlers.go index b903ce81b59f..c10dd27f5140 100644 --- a/beacon-chain/rpc/eth/validator/handlers.go +++ b/beacon-chain/rpc/eth/validator/handlers.go @@ -189,11 +189,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 782dc2f8eb03..0d18448599cd 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -71,10 +71,7 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.Sing if err != nil { return nil, status.Error(codes.Internal, "Could not get target state") } - committeeIndex, err := att.GetCommitteeIndex() - if err != nil { - return nil, status.Error(codes.Internal, "Could not get committee index") - } + 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") diff --git a/beacon-chain/sync/BUILD.bazel b/beacon-chain/sync/BUILD.bazel index 1d83ac98ad6f..86c6d1318672 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/pending_attestations_queue.go b/beacon-chain/sync/pending_attestations_queue.go index 448875c203c2..5a0b7d3231ce 100644 --- a/beacon-chain/sync/pending_attestations_queue.go +++ b/beacon-chain/sync/pending_attestations_queue.go @@ -131,12 +131,20 @@ func (s *Service) processAttestations(ctx context.Context, attestations []ethpb. log.WithError(err).Debug("Could not retrieve attestation prestate") continue } - - valid, err := s.validateUnaggregatedAttWithState(ctx, aggregate, preState) + committee, valid, err := s.validateUnaggregatedAttWithState(ctx, aggregate, preState) if err != nil { log.WithError(err).Debug("Pending unaggregated attestation failed validation") continue } + if aggregate.Version() >= version.Electra { + singleAtt, ok := aggregate.(*ethpb.SingleAttestation) + if !ok { + log.Debugf("Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, aggregate) + continue + } + aggregate = singleAtt.ToAttestationElectra(committee) + } + if valid == pubsub.ValidationAccept { if err := s.cfg.attPool.SaveUnaggregatedAttestation(aggregate); err != nil { log.WithError(err).Debug("Could not save unaggregated attestation") diff --git a/beacon-chain/sync/subscriber_beacon_attestation.go b/beacon-chain/sync/subscriber_beacon_attestation.go index ab440132e477..c049604db010 100644 --- a/beacon-chain/sync/subscriber_beacon_attestation.go +++ b/beacon-chain/sync/subscriber_beacon_attestation.go @@ -25,10 +25,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()) exists, err := s.cfg.attPool.HasAggregatedAttestation(a) diff --git a/beacon-chain/sync/validate_aggregate_proof.go b/beacon-chain/sync/validate_aggregate_proof.go index 614f3aca85ed..f1c05d0de105 100644 --- a/beacon-chain/sync/validate_aggregate_proof.go +++ b/beacon-chain/sync/validate_aggregate_proof.go @@ -169,16 +169,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_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 58495a8d31d6..a0490890cb59 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" @@ -83,12 +82,7 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationReject, err } - 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. @@ -112,12 +106,12 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p 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 @@ -133,7 +127,6 @@ 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 { tracing.AnnotateError(span, err) attBadLmdConsistencyCount.Inc() @@ -145,38 +138,25 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p tracing.AnnotateError(span, err) return pubsub.ValidationIgnore, err } - committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - - var singleAtt *eth.SingleAttestation - 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.validateUnaggregatedAttTopic(ctx, att, preState, *msg.Topic) if validationRes != pubsub.ValidationAccept { return validationRes, err } - if singleAtt != nil { - validationRes, err = validateAttestingIndex(ctx, singleAtt, committee) - if validationRes != pubsub.ValidationAccept { - return validationRes, err - } - } - - validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, preState) + committee, validationRes, err := s.validateUnaggregatedAttWithState(ctx, att, preState) 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) + } + if features.Get().EnableSlasher { // Feed the indexed attestation to slasher if enabled. This action // is done in the background to avoid adding more load to this critical code path. @@ -227,7 +207,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 } @@ -245,79 +225,84 @@ 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 - } 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", ci, count) } return ci, valCount, pubsub.ValidationAccept, nil } -func (s *Service) validateCommitteeIndex(ctx context.Context, a eth.Att) (primitives.CommitteeIndex, pubsub.ValidationResult, error) { - if a.Version() >= version.Electra { - return validateCommitteeIndexElectra(ctx, a) - } - return a.GetData().CommitteeIndex, pubsub.ValidationAccept, nil -} - // This validates beacon unaggregated attestation using the given state, the validation consists of bitfield length and count consistency // and signature verification. -func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.Att, bs state.ReadOnlyBeaconState) (pubsub.ValidationResult, error) { +func (s *Service) validateUnaggregatedAttWithState( + ctx context.Context, + a eth.Att, + bs state.ReadOnlyBeaconState, +) ([]primitives.ValidatorIndex, pubsub.ValidationResult, error) { ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttWithState") defer span.End() - committeeIndex, err := a.GetCommitteeIndex() - if err != nil { - return pubsub.ValidationIgnore, err - } + committeeIndex := a.GetCommitteeIndex() - 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") + var committee []primitives.ValidatorIndex + var err error + + // TODO: add test + // - [REJECT] attestation.data.index == 0 + if a.Version() >= version.Electra { + if committeeIndex != 0 { + return nil, pubsub.ValidationReject, errors.New("attestation data's committee index must be 0") + } + singleAtt, ok := a.(*eth.SingleAttestation) + if !ok { + return nil, pubsub.ValidationReject, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, a) + } + committee, err = helpers.BeaconCommitteeFromState(ctx, bs, a.GetData().Slot, committeeIndex) + if err != nil { + return nil, pubsub.ValidationIgnore, err + } + result, err := validateAttestingIndex(ctx, singleAtt, committee) + if result != pubsub.ValidationAccept { + return nil, result, err + } + } else { + committee, err = helpers.BeaconCommitteeFromState(ctx, bs, a.GetData().Slot, committeeIndex) + if err != nil { + return nil, pubsub.ValidationIgnore, err + } + // Verify number of aggregation bits matches the committee size. + if err = helpers.VerifyBitfieldLength(a.GetAggregationBits(), uint64(len(committee))); err != nil { + return nil, 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 nil, 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( - 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 + return nil, pubsub.ValidationReject, err } - // Verify number of aggregation bits matches the committee size. - if err := helpers.VerifyBitfieldLength(aggregationBits, uint64(len(committee))); err != nil { - return nil, pubsub.ValidationReject, err + result, err := s.validateWithBatchVerifier(ctx, "attestation", set) + if result != pubsub.ValidationAccept { + tracing.AnnotateError(span, err) + return nil, result, err } return committee, pubsub.ValidationAccept, nil 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 dd008107f710..000000000000 --- a/beacon-chain/sync/validate_beacon_attestation_electra.go +++ /dev/null @@ -1,27 +0,0 @@ -package sync - -import ( - "context" - "errors" - - 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] 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() - - if a.GetData().CommitteeIndex != 0 { - return 0, pubsub.ValidationReject, errors.New("attestation data's committee index must be zero") - } - 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 332929ad056e..000000000000 --- a/beacon-chain/sync/validate_beacon_attestation_electra_test.go +++ /dev/null @@ -1,28 +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) { - ci, res, err := validateCommitteeIndexElectra(ctx, ðpb.SingleAttestation{Data: ðpb.AttestationData{}, CommitteeId: 1}) - require.NoError(t, err) - assert.Equal(t, pubsub.ValidationAccept, res) - assert.Equal(t, primitives.CommitteeIndex(1), ci) - }) - t.Run("non-zero committee index in att data", func(t *testing.T) { - _, res, err := validateCommitteeIndexElectra(ctx, ðpb.SingleAttestation{Data: ðpb.AttestationData{CommitteeIndex: 1}}) - assert.NotNil(t, err) - assert.Equal(t, pubsub.ValidationReject, res) - }) -} 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 4cef23af85c6..4498d26f1e87 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" @@ -25,7 +22,7 @@ type Att interface { GetData() *AttestationData CommitteeBitsVal() bitfield.Bitfield GetSignature() []byte - GetCommitteeIndex() (primitives.CommitteeIndex, error) + GetCommitteeIndex() primitives.CommitteeIndex IsNil() bool IsSingle() bool } @@ -150,11 +147,11 @@ func (a *Attestation) CommitteeBitsVal() bitfield.Bitfield { } // 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 -- @@ -206,11 +203,11 @@ func (a *PendingAttestation) GetSignature() []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 -- @@ -257,18 +254,15 @@ func (a *AttestationElectra) CommitteeBitsVal() bitfield.Bitfield { } // 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") + 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])), nil + return primitives.CommitteeIndex(uint64(indices[0])) } // Version -- @@ -322,8 +316,8 @@ func (a *SingleAttestation) GetAggregationBits() bitfield.Bitlist { } // GetCommitteeIndex -- -func (a *SingleAttestation) GetCommitteeIndex() (primitives.CommitteeIndex, error) { - return a.CommitteeId, nil +func (a *SingleAttestation) GetCommitteeIndex() primitives.CommitteeIndex { + return a.CommitteeId } // ToAttestationElectra converts the attestation to an AttestationElectra. @@ -494,6 +488,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 @@ -523,3 +532,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 2c3cfc022e16..ff1efce2ed4c 100755 --- a/proto/prysm/v1alpha1/attestation.pb.go +++ b/proto/prysm/v1alpha1/attestation.pb.go @@ -355,6 +355,69 @@ func (x *AggregateAttestationAndProofElectra) GetSelectionProof() []byte { 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[5] + 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[5] + 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{5} +} + +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 SignedAggregateAttestationAndProof struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -367,7 +430,7 @@ type SignedAggregateAttestationAndProof struct { func (x *SignedAggregateAttestationAndProof) Reset() { *x = SignedAggregateAttestationAndProof{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -380,7 +443,7 @@ func (x *SignedAggregateAttestationAndProof) String() string { func (*SignedAggregateAttestationAndProof) ProtoMessage() {} func (x *SignedAggregateAttestationAndProof) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -393,7 +456,7 @@ func (x *SignedAggregateAttestationAndProof) ProtoReflect() protoreflect.Message // Deprecated: Use SignedAggregateAttestationAndProof.ProtoReflect.Descriptor instead. func (*SignedAggregateAttestationAndProof) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{5} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{6} } func (x *SignedAggregateAttestationAndProof) GetMessage() *AggregateAttestationAndProof { @@ -422,7 +485,7 @@ type SignedAggregateAttestationAndProofElectra struct { func (x *SignedAggregateAttestationAndProofElectra) Reset() { *x = SignedAggregateAttestationAndProofElectra{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -435,7 +498,7 @@ func (x *SignedAggregateAttestationAndProofElectra) String() string { func (*SignedAggregateAttestationAndProofElectra) ProtoMessage() {} func (x *SignedAggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -448,7 +511,7 @@ func (x *SignedAggregateAttestationAndProofElectra) ProtoReflect() protoreflect. // Deprecated: Use SignedAggregateAttestationAndProofElectra.ProtoReflect.Descriptor instead. func (*SignedAggregateAttestationAndProofElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{6} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{7} } func (x *SignedAggregateAttestationAndProofElectra) GetMessage() *AggregateAttestationAndProofElectra { @@ -465,6 +528,61 @@ func (x *SignedAggregateAttestationAndProofElectra) GetSignature() []byte { return 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 AttestationData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -480,7 +598,7 @@ type AttestationData struct { func (x *AttestationData) Reset() { *x = AttestationData{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -493,7 +611,7 @@ func (x *AttestationData) String() string { func (*AttestationData) ProtoMessage() {} func (x *AttestationData) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] + 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 { @@ -506,7 +624,7 @@ func (x *AttestationData) ProtoReflect() protoreflect.Message { // Deprecated: Use AttestationData.ProtoReflect.Descriptor instead. func (*AttestationData) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{7} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{9} } func (x *AttestationData) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { @@ -556,7 +674,7 @@ type Checkpoint struct { func (x *Checkpoint) Reset() { *x = Checkpoint{} 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) } @@ -569,7 +687,7 @@ func (x *Checkpoint) String() string { func (*Checkpoint) ProtoMessage() {} func (x *Checkpoint) 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 { @@ -582,7 +700,7 @@ func (x *Checkpoint) ProtoReflect() protoreflect.Message { // Deprecated: Use Checkpoint.ProtoReflect.Descriptor instead. func (*Checkpoint) 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 *Checkpoint) GetEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch { @@ -698,71 +816,100 @@ var file_proto_prysm_v1alpha1_attestation_proto_rawDesc = []byte{ 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, 0x99, 0x01, 0x0a, 0x22, 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, 0x12, 0x4d, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x33, 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, 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, 0xa7, 0x01, 0x0a, 0x29, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, + 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 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, 0x99, 0x01, 0x0a, 0x22, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, - 0x61, 0x12, 0x54, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3a, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 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, 0x90, 0x03, - 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x78, 0x0a, 0x0f, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 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, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, - 0x82, 0xb5, 0x18, 0x42, 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, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, - 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 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, + 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x4d, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, + 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, + 0xa7, 0x01, 0x0a, 0x29, 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x54, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, + 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, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 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, 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, 0x90, 0x03, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 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, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, + 0x12, 0x78, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 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, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x39, + 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 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, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x12, 0x1a, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 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,33 +924,37 @@ 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{}{ (*Attestation)(nil), // 0: ethereum.eth.v1alpha1.Attestation (*AttestationElectra)(nil), // 1: ethereum.eth.v1alpha1.AttestationElectra (*SingleAttestation)(nil), // 2: ethereum.eth.v1alpha1.SingleAttestation (*AggregateAttestationAndProof)(nil), // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProof (*AggregateAttestationAndProofElectra)(nil), // 4: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - (*SignedAggregateAttestationAndProof)(nil), // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof - (*SignedAggregateAttestationAndProofElectra)(nil), // 6: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra - (*AttestationData)(nil), // 7: ethereum.eth.v1alpha1.AttestationData - (*Checkpoint)(nil), // 8: ethereum.eth.v1alpha1.Checkpoint + (*AggregateAttestationAndProofSingle)(nil), // 5: ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle + (*SignedAggregateAttestationAndProof)(nil), // 6: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof + (*SignedAggregateAttestationAndProofElectra)(nil), // 7: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra + (*SignedAggregateAttestationAndProofSingle)(nil), // 8: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofSingle + (*AttestationData)(nil), // 9: ethereum.eth.v1alpha1.AttestationData + (*Checkpoint)(nil), // 10: ethereum.eth.v1alpha1.Checkpoint } var file_proto_prysm_v1alpha1_attestation_proto_depIdxs = []int32{ - 7, // 0: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 7, // 1: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 7, // 2: ethereum.eth.v1alpha1.SingleAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 0, // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation - 1, // 4: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra - 3, // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof - 4, // 6: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - 8, // 7: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint - 8, // 8: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint - 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 + 9, // 0: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 9, // 1: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 9, // 2: ethereum.eth.v1alpha1.SingleAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 0, // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation + 1, // 4: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra + 2, // 5: ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle.aggregate:type_name -> ethereum.eth.v1alpha1.SingleAttestation + 3, // 6: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof + 4, // 7: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + 5, // 8: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofSingle.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle + 10, // 9: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint + 10, // 10: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint + 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() } @@ -873,7 +1024,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedAggregateAttestationAndProof); i { + switch v := v.(*AggregateAttestationAndProofSingle); i { case 0: return &v.state case 1: @@ -885,7 +1036,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedAggregateAttestationAndProofElectra); i { + switch v := v.(*SignedAggregateAttestationAndProof); i { case 0: return &v.state case 1: @@ -897,7 +1048,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttestationData); i { + switch v := v.(*SignedAggregateAttestationAndProofElectra); i { case 0: return &v.state case 1: @@ -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.(*AttestationData); 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.(*Checkpoint); 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 3b30d6aab801..d6de1745ef81 100644 --- a/proto/prysm/v1alpha1/attestation.proto +++ b/proto/prysm/v1alpha1/attestation.proto @@ -78,6 +78,17 @@ message AggregateAttestationAndProofElectra { bytes selection_proof = 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 SignedAggregateAttestationAndProof { // The aggregated attestation and selection proof itself. AggregateAttestationAndProof message = 1; @@ -94,6 +105,14 @@ message SignedAggregateAttestationAndProofElectra { bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; } +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 AttestationData { // Attestation data includes information on Casper the Friendly Finality Gadget's votes // See: https://arxiv.org/pdf/1710.09437.pdf diff --git a/proto/prysm/v1alpha1/electra.ssz.go b/proto/prysm/v1alpha1/electra.ssz.go index 05bffda17e4d..1d0eb6eb57e0 100644 --- a/proto/prysm/v1alpha1/electra.ssz.go +++ b/proto/prysm/v1alpha1/electra.ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 678c01efb0c60dfd165322b72151277be12cf3c501117900efa16e90a934b94c +// Hash: 22d071b33085dccb532beacb3b5bc5bb67c9a211c2af003b8e20712276885666 package eth import ( @@ -376,6 +376,98 @@ func (a *AggregateAttestationAndProofElectra) HashTreeRootWith(hh *ssz.Hasher) ( 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 SignedAggregateAttestationAndProofElectra object func (s *SignedAggregateAttestationAndProofElectra) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(s) @@ -485,6 +577,89 @@ func (s *SignedAggregateAttestationAndProofElectra) HashTreeRootWith(hh *ssz.Has 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 AttesterSlashingElectra object func (a *AttesterSlashingElectra) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(a) From 0772e04c72bb0314e5466c8b13e70bf9fff84005 Mon Sep 17 00:00:00 2001 From: rkapka Date: Fri, 27 Dec 2024 18:03:18 +0100 Subject: [PATCH 14/17] fix gossip issues --- .../sync/pending_attestations_queue.go | 13 +++- .../sync/validate_beacon_attestation.go | 68 ++++++++----------- 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/beacon-chain/sync/pending_attestations_queue.go b/beacon-chain/sync/pending_attestations_queue.go index a514938c5591..c381d7cb1030 100644 --- a/beacon-chain/sync/pending_attestations_queue.go +++ b/beacon-chain/sync/pending_attestations_queue.go @@ -140,20 +140,27 @@ func (s *Service) processAttestations(ctx context.Context, attestations []ethpb. log.WithError(err).Debug("Could not retrieve attestation prestate") continue } - committee, valid, err := s.validateUnaggregatedAttWithState(ctx, aggregate, preState) + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, aggregate.GetData().Slot, aggregate.GetCommitteeIndex()) if err != nil { - log.WithError(err).Debug("Pending unaggregated attestation failed validation") + log.WithError(err).Debug("Could not retrieve committee from state") continue } + attesterIndex := primitives.ValidatorIndex(0) if aggregate.Version() >= version.Electra { + var ok bool singleAtt, ok := aggregate.(*ethpb.SingleAttestation) if !ok { log.Debugf("Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, aggregate) continue } + attesterIndex = singleAtt.GetAttesterIndex() aggregate = singleAtt.ToAttestationElectra(committee) } - + valid, err := s.validateUnaggregatedAttWithState(ctx, aggregate, attesterIndex, preState, committee) + 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 { diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index a0490890cb59..e3a801304655 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -144,19 +144,27 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return validationRes, err } - committee, validationRes, err := s.validateUnaggregatedAttWithState(ctx, att, preState) - if validationRes != pubsub.ValidationAccept { - return validationRes, err + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err } + attesterIndex := primitives.ValidatorIndex(0) 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) } + attesterIndex = singleAtt.AttesterIndex att = singleAtt.ToAttestationElectra(committee) } + validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, attesterIndex, preState, committee) + if validationRes != pubsub.ValidationAccept { + return validationRes, err + } + if features.Get().EnableSlasher { // Feed the indexed attestation to slasher if enabled. This action // is done in the background to avoid adding more load to this critical code path. @@ -247,48 +255,35 @@ func (s *Service) validateCommitteeIndex( func (s *Service) validateUnaggregatedAttWithState( ctx context.Context, a eth.Att, + attestingIndex primitives.ValidatorIndex, bs state.ReadOnlyBeaconState, -) ([]primitives.ValidatorIndex, pubsub.ValidationResult, error) { + committee []primitives.ValidatorIndex, +) (pubsub.ValidationResult, error) { ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttWithState") defer span.End() - committeeIndex := a.GetCommitteeIndex() - - var committee []primitives.ValidatorIndex - var err error - // TODO: add test // - [REJECT] attestation.data.index == 0 if a.Version() >= version.Electra { - if committeeIndex != 0 { - return nil, pubsub.ValidationReject, errors.New("attestation data's committee index must be 0") + if a.GetData().GetCommitteeIndex() != 0 { + log.Info("a.GetData().GetCommitteeIndex() != 0") + return pubsub.ValidationReject, errors.New("attestation data's committee index must be 0") } - singleAtt, ok := a.(*eth.SingleAttestation) - if !ok { - return nil, pubsub.ValidationReject, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, a) - } - committee, err = helpers.BeaconCommitteeFromState(ctx, bs, a.GetData().Slot, committeeIndex) - if err != nil { - return nil, pubsub.ValidationIgnore, err - } - result, err := validateAttestingIndex(ctx, singleAtt, committee) + result, err := validateAttestingIndex(ctx, attestingIndex, committee) if result != pubsub.ValidationAccept { - return nil, result, err + log.Info("validateAttestingIndex") + return result, err } } else { - committee, err = helpers.BeaconCommitteeFromState(ctx, bs, a.GetData().Slot, committeeIndex) - if err != nil { - return nil, pubsub.ValidationIgnore, err - } // Verify number of aggregation bits matches the committee size. - if err = helpers.VerifyBitfieldLength(a.GetAggregationBits(), uint64(len(committee))); err != nil { - return nil, pubsub.ValidationReject, err + 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 nil, pubsub.ValidationReject, errors.New("attestation bitfield is invalid") + return pubsub.ValidationReject, errors.New("attestation bitfield is invalid") } } @@ -296,25 +291,22 @@ func (s *Service) validateUnaggregatedAttWithState( if err != nil { tracing.AnnotateError(span, err) attBadSignatureBatchCount.Inc() - return nil, pubsub.ValidationReject, err - } - - result, err := s.validateWithBatchVerifier(ctx, "attestation", set) - if result != pubsub.ValidationAccept { - tracing.AnnotateError(span, err) - return nil, result, err + return pubsub.ValidationReject, err } - return committee, pubsub.ValidationAccept, nil + return s.validateWithBatchVerifier(ctx, "attestation", set) } -func validateAttestingIndex(ctx context.Context, a *eth.SingleAttestation, committee []primitives.ValidatorIndex) (pubsub.ValidationResult, error) { +func validateAttestingIndex( + ctx context.Context, + attestingIndex primitives.ValidatorIndex, + committee []primitives.ValidatorIndex, +) (pubsub.ValidationResult, error) { _, span := trace.StartSpan(ctx, "sync.validateAttestingIndex") defer span.End() // _[REJECT]_ The attester is a member of the committee -- i.e. // `attestation.attester_index in get_beacon_committee(state, attestation.data.slot, index)`. - attestingIndex := a.GetAttestingIndex() inCommittee := false for _, ix := range committee { if attestingIndex == ix { From 9345e6670e673ab28fe2b7961db12d10dbf1da06 Mon Sep 17 00:00:00 2001 From: rkapka Date: Tue, 31 Dec 2024 12:57:57 +0100 Subject: [PATCH 15/17] cleanup --- .../sync/pending_attestations_queue.go | 12 +++++-- .../sync/validate_beacon_attestation.go | 36 +++++++++++-------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/beacon-chain/sync/pending_attestations_queue.go b/beacon-chain/sync/pending_attestations_queue.go index c381d7cb1030..86ea67db29dc 100644 --- a/beacon-chain/sync/pending_attestations_queue.go +++ b/beacon-chain/sync/pending_attestations_queue.go @@ -145,7 +145,14 @@ func (s *Service) processAttestations(ctx context.Context, attestations []ethpb. log.WithError(err).Debug("Could not retrieve committee from state") continue } - attesterIndex := primitives.ValidatorIndex(0) + valid, err := validateAttesterData(ctx, aggregate, committee) + if err != nil { + log.WithError(err).Debug("Could not validate attester data") + continue + } else if valid != pubsub.ValidationAccept { + log.Debug("Attestation failed attester data validation") + continue + } if aggregate.Version() >= version.Electra { var ok bool singleAtt, ok := aggregate.(*ethpb.SingleAttestation) @@ -153,10 +160,9 @@ func (s *Service) processAttestations(ctx context.Context, attestations []ethpb. log.Debugf("Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, aggregate) continue } - attesterIndex = singleAtt.GetAttesterIndex() aggregate = singleAtt.ToAttestationElectra(committee) } - valid, err := s.validateUnaggregatedAttWithState(ctx, aggregate, attesterIndex, preState, committee) + valid, err = s.validateUnaggregatedAttWithState(ctx, aggregate, preState) if err != nil { log.WithError(err).Debug("Pending unaggregated attestation failed validation") continue diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index e3a801304655..c65ecaec78ba 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -150,17 +150,20 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationIgnore, err } - attesterIndex := primitives.ValidatorIndex(0) + 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) } - attesterIndex = singleAtt.AttesterIndex att = singleAtt.ToAttestationElectra(committee) } - validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, attesterIndex, preState, committee) + validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, preState) if validationRes != pubsub.ValidationAccept { return validationRes, err } @@ -238,6 +241,9 @@ func (s *Service) validateCommitteeIndex( a eth.Att, bs state.ReadOnlyBeaconState, ) (primitives.CommitteeIndex, uint64, pubsub.ValidationResult, error) { + 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 @@ -250,26 +256,19 @@ func (s *Service) validateCommitteeIndex( return ci, valCount, pubsub.ValidationAccept, nil } -// This validates beacon unaggregated attestation using the given state, the validation consists of bitfield length and count consistency -// and signature verification. -func (s *Service) validateUnaggregatedAttWithState( +func validateAttesterData( ctx context.Context, a eth.Att, - attestingIndex primitives.ValidatorIndex, - bs state.ReadOnlyBeaconState, committee []primitives.ValidatorIndex, ) (pubsub.ValidationResult, error) { - ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttWithState") - defer span.End() - // TODO: add test // - [REJECT] attestation.data.index == 0 if a.Version() >= version.Electra { - if a.GetData().GetCommitteeIndex() != 0 { - log.Info("a.GetData().GetCommitteeIndex() != 0") - return pubsub.ValidationReject, errors.New("attestation data's committee index must be 0") + 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, attestingIndex, committee) + result, err := validateAttestingIndex(ctx, singleAtt.AttesterIndex, committee) if result != pubsub.ValidationAccept { log.Info("validateAttestingIndex") return result, err @@ -286,6 +285,13 @@ func (s *Service) validateUnaggregatedAttWithState( return pubsub.ValidationReject, errors.New("attestation bitfield is invalid") } } + return pubsub.ValidationAccept, nil +} + +// 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() set, err := blocks.AttestationSignatureBatch(ctx, bs, []eth.Att{a}) if err != nil { From bd823352689d4156e0cff3375579de939a73d9f1 Mon Sep 17 00:00:00 2001 From: rkapka Date: Tue, 31 Dec 2024 14:33:14 +0100 Subject: [PATCH 16/17] tests --- .../core/helpers/beacon_committee_test.go | 7 + .../sync/pending_attestations_queue_test.go | 87 +++++++-- .../sync/validate_aggregate_proof_test.go | 9 +- .../sync/validate_beacon_attestation.go | 4 +- .../sync/validate_beacon_attestation_test.go | 173 +++++++++++++++++- 5 files changed, 251 insertions(+), 29 deletions(-) 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/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/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 c65ecaec78ba..f7dc4c6c4fcf 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -241,6 +241,7 @@ func (s *Service) validateCommitteeIndex( a eth.Att, bs state.ReadOnlyBeaconState, ) (primitives.CommitteeIndex, uint64, pubsub.ValidationResult, error) { + // - [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") } @@ -261,8 +262,6 @@ func validateAttesterData( a eth.Att, committee []primitives.ValidatorIndex, ) (pubsub.ValidationResult, error) { - // TODO: add test - // - [REJECT] attestation.data.index == 0 if a.Version() >= version.Electra { singleAtt, ok := a.(*eth.SingleAttestation) if !ok { @@ -270,7 +269,6 @@ func validateAttesterData( } result, err := validateAttestingIndex(ctx, singleAtt.AttesterIndex, committee) if result != pubsub.ValidationAccept { - log.Info("validateAttestingIndex") return result, err } } else { 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() From cb59940e60954ce872601d407864fa6b2d2c37e9 Mon Sep 17 00:00:00 2001 From: rkapka Date: Thu, 2 Jan 2025 14:03:43 +0100 Subject: [PATCH 17/17] reduce cognitive complexity --- .../sync/pending_attestations_queue.go | 191 +++++++++--------- 1 file changed, 101 insertions(+), 90 deletions(-) diff --git a/beacon-chain/sync/pending_attestations_queue.go b/beacon-chain/sync/pending_attestations_queue.go index 86ea67db29dc..7fc849b5fabe 100644 --- a/beacon-chain/sync/pending_attestations_queue.go +++ b/beacon-chain/sync/pending_attestations_queue.go @@ -91,106 +91,117 @@ 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 - } - committee, err := helpers.BeaconCommitteeFromState(ctx, preState, aggregate.GetData().Slot, aggregate.GetCommitteeIndex()) - if err != nil { - log.WithError(err).Debug("Could not retrieve committee from state") - continue - } - valid, err := validateAttesterData(ctx, aggregate, committee) - if err != nil { - log.WithError(err).Debug("Could not validate attester data") - continue - } else if valid != pubsub.ValidationAccept { - log.Debug("Attestation failed attester data validation") - continue + if err := s.cfg.attPool.SaveAggregatedAttestation(aggregate); err != nil { + log.WithError(err).Debug("Could not save aggregate attestation") + return } - if aggregate.Version() >= version.Electra { - var ok bool - singleAtt, ok := aggregate.(*ethpb.SingleAttestation) - if !ok { - log.Debugf("Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, aggregate) - continue - } - aggregate = singleAtt.ToAttestationElectra(committee) + } + + s.setAggregatorIndexEpochSeen(aggregate.GetData().Target.Epoch, att.AggregateAttestationAndProof().GetAggregatorIndex()) + + // 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 } - valid, err = s.validateUnaggregatedAttWithState(ctx, aggregate, preState) - if err != nil { - log.WithError(err).Debug("Pending unaggregated attestation failed validation") - continue + } else { + if err := s.cfg.attPool.SaveUnaggregatedAttestation(att); err != nil { + log.WithError(err).Debug("Could not save unaggregated attestation") + return } - 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.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") - 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") - } - } + 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") } } }