diff --git a/p2p/MessageValidation/ReceivedMessagesEstimation.md b/p2p/MessageValidation/ReceivedMessagesEstimation.md
index f16349e..391eccd 100644
--- a/p2p/MessageValidation/ReceivedMessagesEstimation.md
+++ b/p2p/MessageValidation/ReceivedMessagesEstimation.md
@@ -1,5 +1,8 @@
# Estimation of amount of messages received
+> [!WARNING]
+> This document is deprecated due to protocol changes as of the Alan and Boole forks.
+
To play with the below formulas, follow this [google sheet link](https://docs.google.com/spreadsheets/d/1TpXnVFzF4eGiQarXuPBrOIU4tJXhzOHav9PkGve3_Qc/edit?usp=sharing).
## Probability of having a duty per slot
diff --git a/p2p/MessageValidation/Rules.md b/p2p/MessageValidation/Rules.md
index 4959479..a871265 100644
--- a/p2p/MessageValidation/Rules.md
+++ b/p2p/MessageValidation/Rules.md
@@ -118,15 +118,15 @@ var (
ErrUnexpectedPrepareJustifications = Error{text: "message has a prepare justification but it's not a proposal", reject: true}
- ErrPartialSigOneSigner = Error{text: "partial signature message with len(signers) != 1", reject: true}
- ErrTooManyPartialSignatureMessages = Error{text: "too many signatures for cluster in partial signature message"}
- ErrTripleValidatorIndexInPartialSignatures = Error{text: "validator index appear 3 times in partial signature message", reject: true}
- ErrNoPartialSignatureMessages = Error{text: "no partial signature messages", reject: true}
- ErrInconsistentSigners = Error{text: "inconsistent signers", reject: true}
- ErrValidatorIndexMismatch = Error{text: "validator index mismatch"}
- ErrInvalidPartialSignatureType = Error{text: "invalid partial signature type", reject: true}
- ErrPartialSignatureTypeRoleMismatch = Error{text: "partial signature type and role don't match", reject: true}
- ErrInvalidPartialSignatureTypeCount = Error{text: "sent more partial signature messages of a certain type than allowed", reject: true}
+ ErrPartialSigOneSigner = Error{text: "partial signature message with len(signers) != 1", reject: true}
+ ErrTooManyPartialSignatureMessages = Error{text: "too many signatures for cluster in partial signature message"}
+ ErrTooManyEqualValidatorIndicesInPartialSignatures = Error{text: "validator index appears too many times in partial signature message", reject: true}
+ ErrNoPartialSignatureMessages = Error{text: "no partial signature messages", reject: true}
+ ErrInconsistentSigners = Error{text: "inconsistent signers", reject: true}
+ ErrValidatorIndexMismatch = Error{text: "validator index mismatch"}
+ ErrInvalidPartialSignatureType = Error{text: "invalid partial signature type", reject: true}
+ ErrPartialSignatureTypeRoleMismatch = Error{text: "partial signature type and role don't match", reject: true}
+ ErrInvalidPartialSignatureTypeCount = Error{text: "sent more partial signature messages of a certain type than allowed", reject: true}
ErrTooManyDutiesPerEpoch = Error{text: "too many duties per epoch"}
ErrNoDuty = Error{text: "no duty for this epoch"}
@@ -140,14 +140,13 @@ The main structure is the `MessageValidation` structure which has a `ValidatePub
```go
const (
- MaxMsgSize = 4945164
- maxConsensusMsgSize = 722412
- maxPartialSignatureMsgSize = 144020
+ MaxMsgSize = 9114816 // Source: https://github.com/ssvlabs/ssv-spec/blob/a65134ed45c932588c17d421173923f0216c6c73/types/spectest/tests/maxmsgsize/max_signed_ssv_message.go#L11
+ maxConsensusMsgSize = 722480 // Source: https://github.com/ssvlabs/ssv-spec/blob/a65134ed45c932588c17d421173923f0216c6c73/types/spectest/tests/maxmsgsize/max_ssv_message.go#L9
+ maxPartialSignatureMsgSize = 727000 // Source: https://github.com/ssvlabs/ssv-spec/blob/a65134ed45c932588c17d421173923f0216c6c73/types/spectest/tests/maxmsgsize/max_ssv_message.go#L10
maxSSVMessageDataSize = max(maxConsensusMsgSize, maxPartialSignatureMsgSize)
- PartialSignatureSize = 48
- MessageSignatureSize = 256
- SyncCommitteeSize = 512
- MaxSignaturesInSyncCommitteeContribution = 13
+ PartialSignatureSize = 96 // Source: https://github.com/ssvlabs/ssv-spec/blob/a65134ed45c932588c17d421173923f0216c6c73/types/partial_sig_message.go#L80 and https://eth2book.info/latest/part2/building_blocks/signatures/#signing
+ MessageSignatureSize = 256 // Source: https://github.com/ssvlabs/ssv-spec/blob/a65134ed45c932588c17d421173923f0216c6c73/types/messages.go#L128
+ SyncCommitteeSize = 512 // Source: https://github.com/ethereum/consensus-specs/blob/master/specs/altair/beacon-chain.md#sync-committee
)
type MessageValidation struct {
@@ -423,19 +422,19 @@ func (mv *MessageValidation) ValidatePubSubMessage(pmsg *pubsub.Message) error {
### Semantics General Rules
-| Verification | Error | Classification | Explanation |
-| -------------------- | ------------------------- | -------------- | --------------------------------------------------------------------- |
-| Signers in committee | ErrSignerNotInCommittee | Reject | Signers must belong to validator's or CommitteeID's committee. |
-| Different Domain | ErrWrongDomain | Ignore | MsgID.Domain is different than self domain. |
-| Invalid Role | ErrInvalidRole | Reject | MsgID.Role is not known. |
-| Validator exists | ErrUnknownValidator | Ignore | If MsgID.SenderID is a validator, it must exist. |
-| Active Validator ID | ErrValidatorNotAttesting | Ignore | If MsgID.SenderID is a validator, it must be active active validator. |
-| Validator Liquidated | ErrValidatorLiquidated | Ignore | If MsgID.SenderID is a validator, it must not be liquidated. |
-| CommitteeID exists | ErrNonExistentCommitteeID | Ignore | If MsgID.SenderID is a committee, it must exist. |
-| Wrong topic | ErrIncorrectTopic | Ignore | The message should be sent in the correct topic |
-| Event Message | ErrEventMessage | Reject | MsgType can't be of event message. |
-| DKG Message | ErrDKGMessage | Reject | MsgType can't be of DKG message. |
-| Unknown MsgType | ErrUnknownSSVMessageType | Reject | MsgType is not known. |
+| Verification | Error | Classification | Explanation |
+| -------------------- | ------------------------- | -------------- |--------------------------------------------------------------------------------------------------------------------------------------------|
+| Signers in committee | ErrSignerNotInCommittee | Reject | Signers must belong to validator's or CommitteeID's committee. |
+| Different Domain | ErrWrongDomain | Ignore | MsgID.Domain is different than self domain. |
+| Invalid Role | ErrInvalidRole | Reject | MsgID.Role is wrong (not `RoleCommittee`, `RoleProposer`, `RoleValidatorRegistration`, `RoleVoluntaryExit`, or `RoleAggregatorCommittee`). |
+| Validator exists | ErrUnknownValidator | Ignore | If MsgID.SenderID is a validator, it must exist. |
+| Active Validator ID | ErrValidatorNotAttesting | Ignore | If MsgID.SenderID is a validator, it must be active active validator. |
+| Validator Liquidated | ErrValidatorLiquidated | Ignore | If MsgID.SenderID is a validator, it must not be liquidated. |
+| CommitteeID exists | ErrNonExistentCommitteeID | Ignore | If MsgID.SenderID is a committee, it must exist. |
+| Wrong topic | ErrIncorrectTopic | Ignore | The message should be sent in the correct topic |
+| Event Message | ErrEventMessage | Reject | MsgType can't be of event message. |
+| DKG Message | ErrDKGMessage | Reject | MsgType can't be of DKG message. |
+| Unknown MsgType | ErrUnknownSSVMessageType | Reject | MsgType is not known. |
```go
@@ -477,7 +476,7 @@ func (mv *MessageValidation) ValidateSemantics(peerID peer.ID, signedSSVMessage
}
senderID := signedSSVMessage.SSVMessage.MsgID.GetSenderID()
- if role != types.RoleCommittee {
+ if !isCommitteeRole(role) {
validatorPK := senderID
// Rule: Validator does not exist
@@ -521,6 +520,10 @@ func (mv *MessageValidation) ValidateSemantics(peerID peer.ID, signedSSVMessage
return ErrUnknownSSVMessageType
}
}
+
+func isCommitteeRole(role types.RunnerRole) bool {
+ return role == types.RoleCommittee || role == types.RoleAggregatorCommittee
+}
```
### Consensus
@@ -732,14 +735,14 @@ func (mv *MessageValidation) ValidateQBFTLogic(peerID peer.ID, signedSSVMessage
#### Duty Logic
-| Verification | Error | Classification | Explanation |
-| ------------------------- | ----------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Already advanced slot | ErrSlotAlreadyAdvanced | Ignore | (Non-committee roles) Signer already advanced to later slot. |
-| Invalid role for consensus | ErrUnexpectedConsensusMessage | Reject | SSVMessage.MsgID.Role must not be ValidatorRegistration or VoluntaryExit. |
-| No beacon duty | ErrNoDuty | Ignore | If Proposal or Sync committee contribution duty, check if duty exists with beacon node. |
-| Slot not in time for role | ErrEarlySlotMessage or ErrLateSlotMessage | Ignore | Current time must be between duty's starting time and
+34 (committee and aggregator) or +3 (else) slots. |
-| Too many duties per epoch | ErrTooManyDutiesPerEpoch | Ignore | If role is either aggregator, voluntary exit and validator registration,
it's allowed 2 duties per epoch. Else if committee,
2*V (if no validator is doing sync committee).
Else accept. |
-| Valid round for role | ErrRoundTooHigh | Reject | For committee and aggregation, round can go up to 12. Else, it can go up to 6. |
+| Verification | Error | Classification | Explanation |
+| ------------------------- | ----------------------------- | -------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Already advanced slot | ErrSlotAlreadyAdvanced | Ignore | (Non-committee roles) Signer already advanced to later slot. |
+| Invalid role for consensus | ErrUnexpectedConsensusMessage | Reject | SSVMessage.MsgID.Role must not be ValidatorRegistration or VoluntaryExit. |
+| No beacon duty | ErrNoDuty | Ignore | If Proposal duty, check if duty exists with beacon node. |
+| Slot not in time for role | ErrEarlySlotMessage or ErrLateSlotMessage | Ignore | Current time must be between duty's starting time and
+34 (committee and aggregator committee) or +3 (else) slots. |
+| Too many duties per epoch | ErrTooManyDutiesPerEpoch | Ignore | If role is either voluntary exit and validator registration,
it's allowed 2 duties per epoch. Else if committee or aggregator committee,
2*V (if no validator is doing sync committee).
Else accept. |
+| Valid round for role | ErrRoundTooHigh | Reject | For committee and aggregator committee, round can go up to 12. Else, it can go up to 6. |
```go
@@ -757,7 +760,7 @@ func (mv *MessageValidation) ValidateQBFTMessageByDutyLogic(peerID peer.ID, sign
}
type SSVMessage struct {
MsgType MsgType
- MsgID MessageID -> Role must have consensus, Must be assigned to duty if role is Proposal or Sync Committee Aggregator
+ MsgID MessageID -> Role must have consensus, Must be assigned to duty if role is Proposal
Data []byte
}
type Message struct {
@@ -777,7 +780,7 @@ func (mv *MessageValidation) ValidateQBFTMessageByDutyLogic(peerID peer.ID, sign
_ = qbftMessage.Decode(signedSSVMessage.SSVMessage.Data)
// Rule: Height must not be "old". I.e., signer must not have already advanced to a later slot.
- if signedSSVMessage.SSVMessage.MsgID.GetRoleType() != types.RoleCommittee { // Rule only for validator runners
+ if !isCommitteeRole(signedSSVMessage.SSVMessage.MsgID.GetRoleType()) { // Rule only for validator runners
if !mv.MessageFromOldSlot(peerID, signedSSVMessage.SSVMessage.MsgID, qbftMessage.Height) {
return ErrSlotAlreadyAdvanced
}
@@ -788,13 +791,13 @@ func (mv *MessageValidation) ValidateQBFTMessageByDutyLogic(peerID peer.ID, sign
return ErrUnexpectedConsensusMessage
}
- // Rule: For proposal and sync committee aggregation duties, we check if the validator is assigned to it
- if err := mv.ValidBeaconDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), signedSSVMessage.SSVMessage.MsgID.GetRoleType(), phase0.Slot(qbftMessage.Height)); err != nil {
+ // Rule: For proposer duty, we check if the validator is assigned to it
+ if err := mv.ValidProposerDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), signedSSVMessage.SSVMessage.MsgID.GetRoleType(), phase0.Slot(qbftMessage.Height)); err != nil {
return err
}
// Rule: current slot(height) must be between duty's starting slot and:
- // - duty's starting slot + 34 (committee and aggregation)
+ // - duty's starting slot + 34 (committee and aggregator committee)
// - duty's starting slot + 3 (other types)
if err != mv.ValidDutySlot(peerID, phase0.Slot(qbftMessage.Height), signedSSVMessage.SSVMessage.MsgID.GetRoleType()); err != nil {
// Err should be ErrEarlySlotMessage or ErrLateSlotMessage
@@ -802,15 +805,15 @@ func (mv *MessageValidation) ValidateQBFTMessageByDutyLogic(peerID peer.ID, sign
}
// Rule: valid number of duties per epoch:
- // - 2 for aggregation, voluntary exit and validator registration
- // - 2*V for Committee duty (where V is the number of validators in the cluster) (if no validator is doing sync committee in this epoch)
+ // - 2 for voluntary exit and validator registration
+ // - 2*V for committee and aggregator committee duty (where V is the number of validators in the cluster) (if no validator is doing sync committee in this epoch)
// - else, accept
if !mv.ValidNumberOfDutiesPerEpoch(peerID, signedSSVMessage.SSVMessage.MsgID, phase0.Slot(qbftMessage.Height)) {
return ErrTooManyDutiesPerEpoch
}
// Rule: Round cut-offs for roles:
- // - 12 (committee and aggregation)
+ // - 12 (committee and aggregator committee)
// - 6 (other types)
if !mv.ValidRoundForRole(qbftMessage.Round, signedSSVMessage.SSVMessage.MsgID.GetRoleType()) {
return ErrRoundTooHigh
@@ -819,7 +822,7 @@ func (mv *MessageValidation) ValidateQBFTMessageByDutyLogic(peerID peer.ID, sign
return nil
}
-func (mv *MessageValidation) ValidBeaconDuty() error {
+func (mv *MessageValidation) ValidProposerDuty() error {
// Rule: For a proposal duty message, we check if the validator is assigned to it
if signedSSVMessage.SSVMessage.MsgID.GetRoleType() == types.RoleProposer {
@@ -828,13 +831,6 @@ func (mv *MessageValidation) ValidBeaconDuty() error {
}
}
- // Rule: For a sync committee aggregation duty message, we check if the validator is assigned to it
- if signedSSVMessage.SSVMessage.MsgID.GetRoleType() == types.RoleSyncCommitteeContribution {
- if !mv.HasSyncCommitteeDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), phase0.Slot(qbftMessage.Height)) {
- return ErrNoDuty
- }
- }
-
return nil
}
@@ -844,16 +840,16 @@ func (mv *MessageValidation) ValidBeaconDuty() error {
#### Semantics
-| Verification | Error | Classification | Explanation |
-| -------------------------- | ----------------------------------- | -------------- | ----------- |
-| More than one signer | ErrPartialSigOneSigner | Reject | Must have only 1 signer. |
-| Unexpected FullData | ErrFullDataNotInConsensusMessage | Reject | Must not have FullData. |
-| Unknown type | ErrInvalidPartialSignatureType | Reject | Type not known. |
-| Wrong type for role | ErrPartialSignatureTypeRoleMismatch | Reject | Type must match role:
PostConsensusPartialSig for Committee,
RandaoPartialSig or PostConsensusPartialSig for Proposer,
SelectionProofPartialSig or PostConsensusPartialSig for Aggregator,
SelectionProofPartialSig or PostConsensusPartialSig for Sync committee contribution,
ValidatorRegistrationPartialSig for Validator Registration,
VoluntaryExitPartialSig for Voluntary Exit |
-| No PartialSignatureMessage | ErrNoPartialSignatureMessages | Reject | Message must have at least one PartialSignatureMessage. |
-| Wrong BLS Signature Size | ErrWrongBLSSignatureSize | Reject | $\forall i$ PartialSignatureMessages.Message[i].Signature must have the correct length. |
-| Inconsistent signer | ErrInconsistentSigners | Reject | $\forall i$ PartialSignatureMessages.Message[i].Signer must be the same as the
SignedSSVMessage.OperatorIDs[i]. |
-| Validtor's index mismatch | ErrValidatorIndexMismatch | Ignore | $\forall i$ PartialSignatureMessages.Message[i].ValidatorIndex must belong to SSVMessage.SenderID(). |
+| Verification | Error | Classification | Explanation |
+|----------------------------| ----------------------------------- | -------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| More than one signer | ErrPartialSigOneSigner | Reject | Must have only 1 signer. |
+| Unexpected FullData | ErrFullDataNotInConsensusMessage | Reject | Must not have FullData. |
+| Unknown type | ErrInvalidPartialSignatureType | Reject | Type not known. |
+| Wrong type for role | ErrPartialSignatureTypeRoleMismatch | Reject | Type must match role:
PostConsensusPartialSig for Committee,
RandaoPartialSig or PostConsensusPartialSig for Proposer,
AggregatorCommitteePartialSig or PostConsensusPartialSig for AggregatorCommittee,
ValidatorRegistrationPartialSig for Validator Registration,
VoluntaryExitPartialSig for Voluntary Exit |
+| No PartialSignatureMessage | ErrNoPartialSignatureMessages | Reject | Message must have at least one PartialSignatureMessage. |
+| Wrong BLS Signature Size | ErrWrongBLSSignatureSize | Reject | $\forall i$ PartialSignatureMessages.Message[i].Signature must have the correct length. |
+| Inconsistent signer | ErrInconsistentSigners | Reject | $\forall i$ PartialSignatureMessages.Message[i].Signer must be the same as the
SignedSSVMessage.OperatorIDs[i]. |
+| Validator's index mismatch | ErrValidatorIndexMismatch | Ignore | $\forall i$ PartialSignatureMessages.Message[i].ValidatorIndex must belong to SSVMessage.SenderID(). |
```go
@@ -911,8 +907,7 @@ func (mv *MessageValidation) ValidatePartialSignatureMessageSemantics(peerID pee
// Rule: Partial signature type must match expected type:
// - PostConsensusPartialSig, for Committee duty
// - RandaoPartialSig or PostConsensusPartialSig for Proposer
- // - SelectionProofPartialSig or PostConsensusPartialSig for Aggregator
- // - SelectionProofPartialSig or PostConsensusPartialSig for Sync committee contribution
+ // - AggregatorCommitteePartialSig or PostConsensusPartialSig for AggregatorCommittee
// - ValidatorRegistrationPartialSig for Validator Registration
// - VoluntaryExitPartialSig for Voluntary Exit
if !mv.ExpectedPartialSignatureTypeForRole(partialSignatureMessages.Type, signedSSVMessage.SSVMessage.MsgID) {
@@ -945,15 +940,15 @@ func (mv *MessageValidation) ValidatePartialSignatureMessageSemantics(peerID pee
#### Duty Logic
-| Verification | Error | Classification | Explanation |
-| ---------------------------- | ------------------------ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Already advanced slot | ErrSlotAlreadyAdvanced | Ignore | (Non-committee roles) Signer already advanced to later slot. |
-| No beacon duty | ErrNoDuty | Ignore | If Proposal or Sync committee contribution duty, check if duty exists with beacon node. |
-| Invalid signature type count | ErrInvalidPartialSignatureTypeCount | Reject | It's allow only:
1 PostConsensusPartialSig, for Committee duty,
1 RandaoPartialSig and 1 PostConsensusPartialSig for Proposer,
1 SelectionProofPartialSig and 1 PostConsensusPartialSig for Aggregator,
1 SelectionProofPartialSig and 1 PostConsensusPartialSig for Sync committee contribution,
1 ValidatorRegistrationPartialSig for Validator Registration,
1 VoluntaryExitPartialSig for Voluntary Exit. |
-| Slot not in time for role | ErrEarlySlotMessage or ErrLateSlotMessage | Ignore | Current time must be between duty's starting time and
+34 (committee and aggregator) or +3 (else) slots. |
-| Too many duties per epoch | ErrTooManyDutiesPerEpoch | Ignore | If role is either aggregator, voluntary exit and validator registration,
it's allowed 2 duties per epoch. Else if committee,
2*V (if no validator is doing sync committee).
Else accept. |
-| Too many partial signatures | ErrTooManyPartialSignatureMessages | Reject | For the committee role, it's allowed $min(2*V, V + $ SYNC_COMMITTEE_SIZE $)$
where $V$ is the number of committee's validatos.
For sync committee contribution, it's allowed 13.
Else, only 1. |
-| Triple validator index | ErrTripleValidatorIndexInPartialSignatures | Reject | A validator index can not be associated to more than 2 signatures. |
+| Verification | Error | Classification | Explanation |
+|----------------------------------|----------------------------------------------------| -------------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Already advanced slot | ErrSlotAlreadyAdvanced | Ignore | (Non-committee roles) Signer already advanced to later slot. |
+| No beacon duty | ErrNoDuty | Ignore | If Proposal duty, check if duty exists with beacon node. |
+| Invalid signature type count | ErrInvalidPartialSignatureTypeCount | Reject | It allows only:
1 PostConsensusPartialSig, for Committee duty,
1 RandaoPartialSig and 1 PostConsensusPartialSig for Proposer,
1 AggregatorCommitteePartialSig and 1 PostConsensusPartialSig for AggregatorCommittee,
1 ValidatorRegistrationPartialSig for Validator Registration,
1 VoluntaryExitPartialSig for Voluntary Exit.|
+| Slot not in time for role | ErrEarlySlotMessage or ErrLateSlotMessage | Ignore | Current time must be between duty's starting time and
+34 (committee and aggregator committee) or +3 (else) slots. |
+| Too many duties per epoch | ErrTooManyDutiesPerEpoch | Ignore | If role is either aggregator, voluntary exit and validator registration,
it's allowed 2 duties per epoch. Else if committee or aggregator committee,
2*V (if no validator is doing sync committee).
Else accept. |
+| Too many partial signatures | ErrTooManyPartialSignatureMessages | Reject | For the committee role, it's allowed $min(2*V, V + $ SYNC_COMMITTEE_SIZE $)$
where $V$ is the number of committee's validators.
For the aggregator committee role, it's allowed $min((1+4)*V, V + 4 \times$ SYNC_COMMITTEE_SIZE $)$
where $V$ is the number of committee's validators.
Else, only 1. |
+| Too many equal validator indices | ErrTooManyEqualValidatorIndicesInPartialSignatures | Reject | A validator index can not be associated with more than 2 signatures for the committee role and more than 5 for the aggregator committee role. |
```go
@@ -971,20 +966,20 @@ func (mv *MessageValidation) ValidatePartialSigMessagesByDutyLogic(peerID peer.I
}
type SSVMessage struct {
MsgType MsgType
- MsgID MessageID -> Must be assigned to duty if role is Proposal or Sync Committee Aggregator
+ MsgID MessageID -> Must be assigned to duty if role is Proposal
Data []byte
}
type PartialSignatureMessages struct {
Type PartialSigMsgType -> Message count rules
Slot phase0.Slot -> Must belong to allowed spread, Satisfies a maximum number of duties per epoch for role, Must not be "old"
- Messages []*PartialSignatureMessage -> Valid number of signatures (3 cases: committee duty, sync committee contribution, others)
+ Messages []*PartialSignatureMessage -> Valid number of signatures (3 cases: committee duty, aggregator committee duty, others)
}
type PartialSignatureMessage struct {
PartialSignature Signature
SigningRoot [32]byte
Signer OperatorID
- ValidatorIndex phase0.ValidatorIndex -> Can't appear more than 2 times for role Committee
+ ValidatorIndex phase0.ValidatorIndex -> Can't appear more than 2 (resp. 5) times for role Committee (resp. AggregatorCommittee)
}
*/
@@ -992,25 +987,25 @@ func (mv *MessageValidation) ValidatePartialSigMessagesByDutyLogic(peerID peer.I
var partialSignatureMessages types.PartialSignatureMessages
_ = partialSignatureMessages.Decode(signedSSVMessage.SSVMessage.Data)
+ msgRole := signedSSVMessage.SSVMessage.MsgID.GetRoleType()
// Rule: Height must not be "old". I.e., signer must not have already advanced to a later slot.
- if signedSSVMessage.SSVMessage.MsgID.GetRoleType() != types.RoleCommittee { // Rule only for validator runners
+ if !isCommitteeRole(msgRole) { // Rule only for validator runners
if !mv.MessageFromOldSlot(peerID, signedSSVMessage.SSVMessage.MsgID, partialSignatureMessages.Slot) {
return ErrSlotAlreadyAdvanced
}
}
- // Rule: For proposal and sync committee aggregation duties, we check if the validator is assigned to it
- if err := mv.ValidBeaconDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), signedSSVMessage.SSVMessage.MsgID.GetRoleType(), partialSignatureMessages.Slot); err != nil {
+ // Rule: For proposer duty, we check if the validator is assigned to it
+ if err := mv.ValidProposerDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), signedSSVMessage.SSVMessage.MsgID.GetRoleType(), partialSignatureMessages.Slot); err != nil {
return err
}
// Rule: peer must send only:
// - 1 PostConsensusPartialSig, for Committee duty
// - 1 RandaoPartialSig and 1 PostConsensusPartialSig for Proposer
- // - 1 SelectionProofPartialSig and 1 PostConsensusPartialSig for Aggregator
- // - 1 SelectionProofPartialSig and 1 PostConsensusPartialSig for Sync committee contribution
+ // - 1 AggregatorCommitteePartialSig and 1 PostConsensusPartialSig for AggregatorCommittee
// - 1 ValidatorRegistrationPartialSig for Validator Registration
// - 1 VoluntaryExitPartialSig for Voluntary Exit
if err := mv.ValidPartialSigMessageCount(peerID, signedSSVMessage.SSVMessage.MsgID, &partialSignatureMessages); err != nil {
@@ -1018,7 +1013,7 @@ func (mv *MessageValidation) ValidatePartialSigMessagesByDutyLogic(peerID peer.I
}
// Rule: current slot must be between duty's starting slot and:
- // - duty's starting slot + 34 (committee and aggregation)
+ // - duty's starting slot + 34 (committee and aggregator committee)
// - duty's starting slot + 3 (other duties)
if err := mv.ValidDutySlot(peerID, partialSignatureMessages.Slot, signedSSVMessage.SSVMessage.MsgID.GetRoleType()); err != nil {
// Err should be ErrEarlySlotMessage or ErrLateSlotMessage
@@ -1026,28 +1021,32 @@ func (mv *MessageValidation) ValidatePartialSigMessagesByDutyLogic(peerID peer.I
}
// Rule: valid number of duties per epoch:
- // - 2 for aggregation, voluntary exit and validator registration
- // - 2*V for Committee duty (where V is the number of validators in the cluster) (if no validator is doing sync committee in this epoch)
+ // - 2 for voluntary exit and validator registration
+ // - 2*V for Committee and AggregatorCommittee duty (where V is the number of validators in the cluster) (if no validator is doing sync committee in this epoch)
// - else, accept
if !mv.ValidNumberOfDutiesPerEpoch(peerID, signedSSVMessage.SSVMessage.MsgID, partialSignatureMessages.Slot) {
return ErrTooManyDutiesPerEpoch
}
- if signedSSVMessage.SSVMessage.MsgID.GetRoleType() == types.RoleCommittee {
-
- // Rule: The number of signatures must be <= min(2*V, V + SYNC_COMMITTEE_SIZE) where V is the number of validators assigned to the cluster
- if !mv.ValidNumberOfSignaturesForCommitteeDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), &partialSignatureMessages) {
- return ErrTooManyPartialSignatureMessages
- }
-
- // Rule: a ValidatorIndex can't appear more than 2 times in the []*PartialSignatureMessage list
- if !mv.NoTripleValidatorOccurrence(&partialSignatureMessages) {
- return ErrTripleValidatorIndexInPartialSignatures
- }
- } else if signedSSVMessage.SSVMessage.MsgID.GetRoleType() == types.RoleSyncCommitteeContribution {
- // Rule: The number of signatures must be <= MaxSignaturesInSyncCommitteeContribution for the sync comittee contribution duty
- if len(partialSignatureMessages.Messages) > MaxSignaturesInSyncCommitteeContribution {
- return ErrTooManyPartialSignatureMessages
+ if isCommitteeRole(msgRole) {
+
+ if msgRole == types.RoleCommittee {
+ // Rule: The number of signatures must be <= min(2*V, V + SYNC_COMMITTEE_SIZE) where V is the number of validators assigned to the cluster
+ if !mv.ValidNumberOfSignaturesForCommitteeDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), &partialSignatureMessages) {
+ return ErrTooManyPartialSignatureMessages
+ }
+ }
+
+ if msgRole == types.RoleAggregatorCommittee {
+ // Rule: The number of signatures must be <= min(5*V, V + 4*SYNC_COMMITTEE_SIZE) where V is the number of validators assigned to the cluster
+ if !mv.ValidNumberOfSignaturesForAggregatorCommitteeDuty(signedSSVMessage.SSVMessage.MsgID.GetSenderID(), &partialSignatureMessages) {
+ return ErrTooManyPartialSignatureMessages
+ }
+ }
+
+ // Rule: a ValidatorIndex can't appear more than 2 (resp. 5) times in the []*PartialSignatureMessage list for role Committee (resp. AggregatorCommittee)
+ if mv.TooManyEqualValidatorOccurrence(&partialSignatureMessages, msgRole) {
+ return ErrTooManyEqualValidatorIndicesInPartialSignatures
}
} else {
// Rule: The number of signatures must be 1 for the other types of duties
@@ -1068,4 +1067,4 @@ func (mv *MessageValidation) ValidatePartialSigMessagesByDutyLogic(peerID peer.I
### Rules suggestions for future
- Priority-based message handling: priority based on type and sender.
-- Message aggregation: aggregate similar messages (e.g. wait for a quorum of prepares, commits, round-changes, partial-sig) before delivering to the app.
\ No newline at end of file
+- Message aggregation: aggregate similar messages (e.g. wait for a quorum of prepares, commits, round-changes, partial-sig) before delivering to the app.