diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 627b5f0e8c..f12adc8970 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -150,7 +150,7 @@ Deploy nodes to prod: # +---------------------------+ # | 🟠 Deploy SSV Prater nodes | # +---------------------------+ - #- .k8/production/prater/scripts/deploy-cluster-1--4.sh $DOCKER_REPO_INFRA_PROD $CI_COMMIT_SHA ssv $APP_REPLICAS_INFRA_PROD blox-infra-prod kubernetes-admin@blox-infra-prod ssv.network $K8S_API_VERSION $PROD_HEALTH_CHECK_IMAGE $SSV_NODES_CPU_LIMIT_V3 $SSV_NODES_MEM_LIMIT_V3 + - .k8/production/prater/scripts/deploy-cluster-1--4.sh $DOCKER_REPO_INFRA_PROD $CI_COMMIT_SHA ssv $APP_REPLICAS_INFRA_PROD blox-infra-prod kubernetes-admin@blox-infra-prod ssv.network $K8S_API_VERSION $PROD_HEALTH_CHECK_IMAGE $SSV_NODES_CPU_LIMIT_V3 $SSV_NODES_MEM_LIMIT_V3 # # +----------------------------+ # | 🔴 Deploy SSV Mainnet nodes | @@ -196,7 +196,7 @@ Deploy exporter to prod: # +------------------------------+ # | 🟠 Deploy Prater exporter | # +------------------------------+ - # - .k8/production/prater/scripts/deploy-exporters.sh $DOCKER_REPO_INFRA_PROD $CI_COMMIT_SHA ssv $APP_REPLICAS_INFRA_PROD blox-infra-prod kubernetes-admin@blox-infra-prod ssv.network $K8S_API_VERSION $SSV_EXPORTER_CPU_LIMIT $SSV_EXPORTER_MEM_LIMIT + - .k8/production/prater/scripts/deploy-exporters.sh $DOCKER_REPO_INFRA_PROD $CI_COMMIT_SHA ssv $APP_REPLICAS_INFRA_PROD blox-infra-prod kubernetes-admin@blox-infra-prod ssv.network $K8S_API_VERSION $SSV_EXPORTER_CPU_LIMIT $SSV_EXPORTER_MEM_LIMIT # # +------------------------------+ # │ 🔴 Deploy Mainnet exporter | diff --git a/message/validation/consensus_validation.go b/message/validation/consensus_validation.go index fde979826b..674f148ea6 100644 --- a/message/validation/consensus_validation.go +++ b/message/validation/consensus_validation.go @@ -240,7 +240,7 @@ func (mv *messageValidator) validateSignerBehaviorConsensus( return err } - if !(msgSlot > signerState.Slot || msgSlot == signerState.Slot && msgRound > signerState.Round) { + if msgSlot == signerState.Slot && msgRound == signerState.Round { if mv.hasFullData(signedMsg) && signerState.ProposalData != nil && !bytes.Equal(signerState.ProposalData, signedMsg.FullData) { return ErrDuplicatedProposalWithDifferentData } diff --git a/message/validation/validation.go b/message/validation/validation.go index 2a363efe25..c00b2b8ea3 100644 --- a/message/validation/validation.go +++ b/message/validation/validation.go @@ -77,8 +77,14 @@ type messageValidator struct { dutyStore *dutystore.Store ownOperatorID spectypes.OperatorID operatorIDToPubkeyCache *hashmap.Map[spectypes.OperatorID, *rsa.PublicKey] - selfPID peer.ID - selfAccept bool + + // validationLocks is a map of lock per SSV message ID to + // prevent concurrent access to the same state. + validationLocks map[spectypes.MessageID]*sync.Mutex + validationMutex sync.Mutex + + selfPID peer.ID + selfAccept bool } // NewMessageValidator returns a new MessageValidator with the given network configuration and options. @@ -88,6 +94,7 @@ func NewMessageValidator(netCfg networkconfig.NetworkConfig, opts ...Option) Mes metrics: &nopMetrics{}, netCfg: netCfg, operatorIDToPubkeyCache: hashmap.New[spectypes.OperatorID, *rsa.PublicKey](), + validationLocks: make(map[spectypes.MessageID]*sync.Mutex), } for _, opt := range opts { @@ -431,6 +438,17 @@ func (mv *messageValidator) validateSSVMessage(ssvMessage *spectypes.SSVMessage, return nil, descriptor, e } + // Lock this SSV message ID to prevent concurrent access to the same state. + mv.validationMutex.Lock() + mutex, ok := mv.validationLocks[msg.GetID()] + if !ok { + mutex = &sync.Mutex{} + mv.validationLocks[msg.GetID()] = mutex + } + mutex.Lock() + defer mutex.Unlock() + mv.validationMutex.Unlock() + descriptor.SSVMessageType = ssvMessage.MsgType if mv.nodeStorage != nil { diff --git a/protocol/v2/ssv/runner/runner.go b/protocol/v2/ssv/runner/runner.go index ff833d8c31..9034d5da84 100644 --- a/protocol/v2/ssv/runner/runner.go +++ b/protocol/v2/ssv/runner/runner.go @@ -54,8 +54,7 @@ type BaseRunner struct { BeaconRoleType spectypes.BeaconRole // implementation vars - TimeoutF TimeoutF `json:"-"` - VerifySignatures bool `json:"-"` + TimeoutF TimeoutF `json:"-"` // highestDecidedSlot holds the highest decided duty slot and gets updated after each decided is reached highestDecidedSlot spec.Slot diff --git a/protocol/v2/ssv/runner/runner_signatures.go b/protocol/v2/ssv/runner/runner_signatures.go index edfc608ea7..54e4d9de1e 100644 --- a/protocol/v2/ssv/runner/runner_signatures.go +++ b/protocol/v2/ssv/runner/runner_signatures.go @@ -58,15 +58,13 @@ func (b *BaseRunner) validatePartialSigMsgForSlot( return errors.New("invalid partial sig slot") } - if b.VerifySignatures { - if err := types.VerifyByOperators(signedMsg.GetSignature(), signedMsg, b.Share.DomainType, spectypes.PartialSignatureType, b.Share.Committee); err != nil { - return errors.Wrap(err, "failed to verify PartialSignature") - } + if err := types.VerifyByOperators(signedMsg.GetSignature(), signedMsg, b.Share.DomainType, spectypes.PartialSignatureType, b.Share.Committee); err != nil { + return errors.Wrap(err, "failed to verify PartialSignature") + } - for _, msg := range signedMsg.Message.Messages { - if err := b.verifyBeaconPartialSignature(msg); err != nil { - return errors.Wrap(err, "could not verify Beacon partial Signature") - } + for _, msg := range signedMsg.Message.Messages { + if err := b.verifyBeaconPartialSignature(msg); err != nil { + return errors.Wrap(err, "could not verify Beacon partial Signature") } } diff --git a/protocol/v2/ssv/spectest/msg_processing_type.go b/protocol/v2/ssv/spectest/msg_processing_type.go index 412b92b8da..b962418894 100644 --- a/protocol/v2/ssv/spectest/msg_processing_type.go +++ b/protocol/v2/ssv/spectest/msg_processing_type.go @@ -48,8 +48,6 @@ func RunMsgProcessing(t *testing.T, test *MsgProcessingSpecTest) { } func (test *MsgProcessingSpecTest) RunAsPartOfMultiTest(t *testing.T, logger *zap.Logger) { - test.Runner.GetBaseRunner().VerifySignatures = true - v := ssvtesting.BaseValidator(logger, spectestingutils.KeySetForShare(test.Runner.GetBaseRunner().Share)) v.DutyRunners[test.Runner.GetBaseRunner().BeaconRoleType] = test.Runner v.Network = test.Runner.GetNetwork().(specqbft.Network) // TODO need to align