Skip to content

Commit

Permalink
fix: (DutyScheduler) execute genesis duties at pre-fork (#1608)
Browse files Browse the repository at this point in the history
* use domainType instead of using domainTypeProvider

* change return validatorForTopic to be functional and pass to p2p handshake dynamic domain type

* add logic to proposer scheduler to support pre fork

* add logic to voluntary exit and validator registration schedulers to support genesis

* fix voluntary exit test by fixing it to post-fork

* fix mergeing issues

---------

Co-authored-by: guy muroch <[email protected]>
Co-authored-by: y0sher <[email protected]>
Co-authored-by: moshe-blox <[email protected]>
  • Loading branch information
4 people authored Aug 11, 2024
1 parent 6ec5987 commit 20dba00
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 36 deletions.
3 changes: 1 addition & 2 deletions operator/duties/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ package duties
import (
"context"
"fmt"
"time"

genesisspectypes "github.com/ssvlabs/ssv-spec-pre-cc/types"
"time"

eth2apiv1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec/phase0"
Expand Down
26 changes: 18 additions & 8 deletions operator/duties/validatorregistration.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package duties

import (
"context"
genesisspectypes "github.com/ssvlabs/ssv-spec-pre-cc/types"

"github.com/attestantio/go-eth2-client/spec/phase0"
spectypes "github.com/ssvlabs/ssv-spec/types"
Expand Down Expand Up @@ -49,14 +50,23 @@ func (h *ValidatorRegistrationHandler) HandleDuties(ctx context.Context) {

pk := phase0.BLSPubKey{}
copy(pk[:], share.ValidatorPubKey[:])

h.dutiesExecutor.ExecuteDuties(h.logger, []*spectypes.ValidatorDuty{{
Type: spectypes.BNRoleValidatorRegistration,
ValidatorIndex: share.ValidatorIndex,
PubKey: pk,
Slot: slot,
// no need for other params
}})
if !h.network.PastAlanForkAtEpoch(h.network.Beacon.EstimatedEpochAtSlot(slot)) {
h.dutiesExecutor.ExecuteGenesisDuties(h.logger, []*genesisspectypes.Duty{{
Type: genesisspectypes.BNRoleValidatorRegistration,
ValidatorIndex: share.ValidatorIndex,
PubKey: pk,
Slot: slot,
// no need for other params
}})
} else {
h.dutiesExecutor.ExecuteDuties(h.logger, []*spectypes.ValidatorDuty{{
Type: spectypes.BNRoleValidatorRegistration,
ValidatorIndex: share.ValidatorIndex,
PubKey: pk,
Slot: slot,
// no need for other params
}})
}

validators = append(validators, share.BeaconMetadata.Index)
}
Expand Down
68 changes: 48 additions & 20 deletions operator/duties/voluntary_exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package duties

import (
"context"
genesisspectypes "github.com/ssvlabs/ssv-spec-pre-cc/types"
"math/big"

"github.com/attestantio/go-eth2-client/spec/phase0"
Expand Down Expand Up @@ -57,26 +58,7 @@ func (h *VoluntaryExitHandler) HandleDuties(ctx context.Context) {
next = h.ticker.Next()

h.logger.Debug("🛠 ticker event", fields.Slot(currentSlot))

var dutiesForExecution, pendingDuties []*spectypes.ValidatorDuty

for _, duty := range h.dutyQueue {
if duty.Slot <= currentSlot {
dutiesForExecution = append(dutiesForExecution, duty)
} else {
pendingDuties = append(pendingDuties, duty)
}
}

h.dutyQueue = pendingDuties
h.duties.RemoveSlot(currentSlot - phase0.Slot(h.network.SlotsPerEpoch()))

if dutyCount := len(dutiesForExecution); dutyCount != 0 {
h.dutiesExecutor.ExecuteDuties(h.logger, dutiesForExecution)
h.logger.Debug("executed voluntary exit duties",
fields.Slot(currentSlot),
fields.Count(dutyCount))
}
h.processExecution(currentSlot)

case exitDescriptor, ok := <-h.validatorExitCh:
if !ok {
Expand Down Expand Up @@ -121,6 +103,52 @@ func (h *VoluntaryExitHandler) HandleDuties(ctx context.Context) {
}
}

func (h *VoluntaryExitHandler) processExecution(slot phase0.Slot) {
var dutiesForExecution, pendingDuties []*spectypes.ValidatorDuty

for _, duty := range h.dutyQueue {
if duty.Slot <= slot {
dutiesForExecution = append(dutiesForExecution, duty)
} else {
pendingDuties = append(pendingDuties, duty)
}
}

h.dutyQueue = pendingDuties
h.duties.RemoveSlot(slot - phase0.Slot(h.network.SlotsPerEpoch()))

if !h.network.PastAlanForkAtEpoch(h.network.Beacon.EstimatedEpochAtSlot(slot)) {
toExecute := make([]*genesisspectypes.Duty, 0, len(dutiesForExecution))
for _, d := range dutiesForExecution {
toExecute = append(toExecute, h.toGenesisSpecDuty(d, genesisspectypes.BNRoleVoluntaryExit))
}

if dutyCount := len(dutiesForExecution); dutyCount != 0 {
h.dutiesExecutor.ExecuteGenesisDuties(h.logger, toExecute)
h.logger.Debug("executed voluntary exit duties",
fields.Slot(slot),
fields.Count(dutyCount))
}
return
}

if dutyCount := len(dutiesForExecution); dutyCount != 0 {
h.dutiesExecutor.ExecuteDuties(h.logger, dutiesForExecution)
h.logger.Debug("executed voluntary exit duties",
fields.Slot(slot),
fields.Count(dutyCount))
}
}

func (h *VoluntaryExitHandler) toGenesisSpecDuty(duty *spectypes.ValidatorDuty, role genesisspectypes.BeaconRole) *genesisspectypes.Duty {
return &genesisspectypes.Duty{
Type: role,
PubKey: duty.PubKey,
Slot: duty.Slot,
ValidatorIndex: duty.ValidatorIndex,
}
}

// blockSlot gets slots happened at the same time as block,
// it prevents calling execution client multiple times if there are several validator exit events on the same block
func (h *VoluntaryExitHandler) blockSlot(ctx context.Context, blockNumber uint64) (phase0.Slot, error) {
Expand Down
3 changes: 1 addition & 2 deletions operator/duties/voluntary_exit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

spectypes "github.com/ssvlabs/ssv-spec/types"

"github.com/ssvlabs/ssv/beacon/goclient"
"github.com/ssvlabs/ssv/operator/duties/dutystore"
mocknetwork "github.com/ssvlabs/ssv/protocol/v2/blockchain/beacon/mocks"
)
Expand All @@ -26,7 +25,7 @@ func TestVoluntaryExitHandler_HandleDuties(t *testing.T) {
currentSlot := &SafeValue[phase0.Slot]{}
currentSlot.Set(0)

scheduler, logger, ticker, timeout, cancel, schedulerPool, startFn := setupSchedulerAndMocks(t, []dutyHandler{handler}, currentSlot, goclient.FarFutureEpoch)
scheduler, logger, ticker, timeout, cancel, schedulerPool, startFn := setupSchedulerAndMocks(t, []dutyHandler{handler}, currentSlot, 0)
startFn()

blockByNumberCalls := create1to1BlockSlotMapping(scheduler)
Expand Down
7 changes: 4 additions & 3 deletions operator/validator/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,6 @@ func SetupRunners(
logger *zap.Logger,
options validator.Options,
) runner.ValidatorDutyRunners {
alanDomainType := options.NetworkConfig.AlanDomainType

if options.SSVShare == nil || options.SSVShare.BeaconMetadata == nil {
logger.Error("missing validator metadata", zap.String("validator", hex.EncodeToString(options.SSVShare.ValidatorPubKey[:])))
Expand Down Expand Up @@ -1420,6 +1419,8 @@ func SetupRunners(
}
config.ValueCheckF = valueCheckF

alanDomainType := options.NetworkConfig.AlanDomainType

identifier := spectypes.NewMsgID(alanDomainType, options.SSVShare.Share.ValidatorPubKey[:], role)
qbftCtrl := qbftcontroller.NewController(identifier[:], options.Operator, config, options.OperatorSigner, options.FullNode)
return qbftCtrl
Expand All @@ -1429,6 +1430,7 @@ func SetupRunners(
shareMap[options.SSVShare.ValidatorIndex] = &options.SSVShare.Share

runners := runner.ValidatorDutyRunners{}
alanDomainType := options.NetworkConfig.AlanDomainType
for _, role := range runnersType {
switch role {
//case spectypes.BNRoleAttester:
Expand Down Expand Up @@ -1461,8 +1463,6 @@ func SetupRunners(
}

func SetupGenesisRunners(ctx context.Context, logger *zap.Logger, options validator.Options) genesisrunner.DutyRunners {
genesisDomainType := options.NetworkConfig.GenesisDomainType

if options.SSVShare == nil || options.SSVShare.BeaconMetadata == nil {
logger.Error("missing validator metadata", zap.String("validator", hex.EncodeToString(options.SSVShare.ValidatorPubKey[:])))
return genesisrunner.DutyRunners{} // TODO need to find better way to fix it
Expand Down Expand Up @@ -1504,6 +1504,7 @@ func SetupGenesisRunners(ctx context.Context, logger *zap.Logger, options valida
genesisBeaconNetwork := genesisspectypes.BeaconNetwork(options.NetworkConfig.Beacon.GetBeaconNetwork())

runners := genesisrunner.DutyRunners{}
genesisDomainType := options.NetworkConfig.GenesisDomainType
for _, role := range runnersType {
switch role {
case genesisspectypes.BNRoleAttester:
Expand Down
1 change: 0 additions & 1 deletion protocol/genesis/ssv/runner/validator_registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"

spectypes "github.com/ssvlabs/ssv-spec/types"

v1 "github.com/attestantio/go-eth2-client/api/v1"
Expand Down

0 comments on commit 20dba00

Please sign in to comment.