Skip to content

Commit

Permalink
Bump unit test timeouts for CI
Browse files Browse the repository at this point in the history
  • Loading branch information
jshufro committed Dec 5, 2024
1 parent afa8bb0 commit 93a514d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
- uses: actions/setup-go@v4
with:
go-version: 1.21.8
- run: go test ./...
- run: go test ./... -timeout 30m
21 changes: 7 additions & 14 deletions shared/services/rewards/generator-impl-v8.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ func (r *treeGeneratorImpl_v8) calculateEthRewards(checkBeaconPerformance bool)
validatorReq := eth.EthToWei(32)
for _, nodeInfo := range r.nodeDetails {
// Check if the node is currently opted in for simplicity
if nodeInfo.IsEligible && nodeInfo.IsOptedIn && r.elEndTime.Sub(nodeInfo.OptInTime) > 0 {
if nodeInfo.IsEligible && nodeInfo.OptedInAt(r.elEndTime) {
for _, minipool := range nodeInfo.Minipools {
minipool.CompletedAttestations = map[uint64]bool{0: true}

Expand Down Expand Up @@ -875,8 +875,7 @@ func (r *treeGeneratorImpl_v8) checkDutiesForSlot(attestations []beacon.Attestat
delete(validator.MissingAttestationSlots, attestation.SlotIndex)

// Check if this minipool was opted into the SP for this block
nodeDetails := r.nodeDetails[validator.NodeIndex]
if blockTime.Sub(nodeDetails.OptInTime) < 0 || nodeDetails.OptOutTime.Sub(blockTime) < 0 {
if !validator.node.OptedInAt(blockTime) {
// Not opted in
continue
}
Expand Down Expand Up @@ -1024,9 +1023,6 @@ func (r *treeGeneratorImpl_v8) createMinipoolIndexMap() error {
// Get the details for every node that was opted into the Smoothing Pool for at least some portion of this interval
func (r *treeGeneratorImpl_v8) getSmoothingPoolNodeDetails() error {

farFutureTime := time.Unix(1000000000000000000, 0) // Far into the future
farPastTime := time.Unix(0, 0)

// For each NO, get their opt-in status and time of last change in batches
r.log.Printlnf("%s Getting details of nodes for Smoothing Pool calculation...", r.logPrefix)
nodeCount := uint64(len(r.networkState.NodeDetails))
Expand Down Expand Up @@ -1057,14 +1053,7 @@ func (r *treeGeneratorImpl_v8) getSmoothingPoolNodeDetails() error {
nodeDetails.IsOptedIn = nativeNodeDetails.SmoothingPoolRegistrationState
statusChangeTimeBig := nativeNodeDetails.SmoothingPoolRegistrationChanged
statusChangeTime := time.Unix(statusChangeTimeBig.Int64(), 0)

if nodeDetails.IsOptedIn {
nodeDetails.OptInTime = statusChangeTime
nodeDetails.OptOutTime = farFutureTime
} else {
nodeDetails.OptOutTime = statusChangeTime
nodeDetails.OptInTime = farPastTime
}
nodeDetails.SPRegistrationTime = statusChangeTime

// Get the details for each minipool in the node
for _, mpd := range r.networkState.MinipoolDetailsByNode[nodeDetails.Address] {
Expand Down Expand Up @@ -1092,6 +1081,10 @@ func (r *treeGeneratorImpl_v8) getSmoothingPoolNodeDetails() error {
CompletedAttestations: map[uint64]bool{},
WasActive: true,
AttestationScore: NewQuotedBigInt(0),

node: nodeDetails,
statusChangeTime: time.Unix(nativeMinipoolDetails.StatusTime.Int64(), 0),
status: nativeMinipoolDetails.Status,
})
}
}
Expand Down
62 changes: 34 additions & 28 deletions shared/services/rewards/generator-impl-v9-v10.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"math/big"
"sort"
"strconv"
"sync"
"time"

Expand All @@ -20,6 +21,7 @@ import (
"github.com/rocket-pool/smartnode/shared/services/rewards/fees"
"github.com/rocket-pool/smartnode/shared/services/rewards/ssz_types"
sszbig "github.com/rocket-pool/smartnode/shared/services/rewards/ssz_types/big"
"github.com/rocket-pool/smartnode/shared/services/rewards/validatorindex"

Check failure on line 24 in shared/services/rewards/generator-impl-v9-v10.go

View workflow job for this annotation

GitHub Actions / build

no required module provides package github.com/rocket-pool/smartnode/shared/services/rewards/validatorindex; to add it:
"github.com/rocket-pool/smartnode/shared/services/state"
"github.com/rocket-pool/smartnode/shared/utils/log"
"golang.org/x/sync/errgroup"
Expand All @@ -44,7 +46,7 @@ type treeGeneratorImpl_v9_v10 struct {
smoothingPoolBalance *big.Int
intervalDutiesInfo *IntervalDutiesInfo
slotsPerEpoch uint64
validatorIndexMap map[string]*MinipoolInfo
validatorIndexMap *validatorindex.ValidatorIndexMap[MinipoolInfo]
elStartTime time.Time
elEndTime time.Time
validNetworkCache map[uint64]bool
Expand Down Expand Up @@ -86,7 +88,7 @@ func newTreeGeneratorImpl_v9_v10(rulesetVersion uint64, log *log.ColorLogger, lo
NodeRewards: ssz_types.NodeRewards{},
},
validatorStatusMap: map[rptypes.ValidatorPubkey]beacon.ValidatorStatus{},
validatorIndexMap: map[string]*MinipoolInfo{},
validatorIndexMap: validatorindex.NewValidatorIndexMap[MinipoolInfo](),
elSnapshotHeader: elSnapshotHeader,
snapshotEnd: snapshotEnd,
log: log,
Expand Down Expand Up @@ -507,7 +509,7 @@ func (r *treeGeneratorImpl_v9_v10) calculateEthRewards(checkBeaconPerformance bo
validatorReq := big.NewInt(0).Set(thirtyTwoEth)
for _, nodeInfo := range r.nodeDetails {
// Check if the node is currently opted in for simplicity
if nodeInfo.IsEligible && nodeInfo.IsOptedIn && r.elEndTime.After(nodeInfo.OptInTime) {
if nodeInfo.IsEligible && nodeInfo.OptedInAt(r.elEndTime) {
eligibleBorrowedEth := nodeInfo.EligibleBorrowedEth
_, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nodeInfo.RplStake)
for _, minipool := range nodeInfo.Minipools {
Expand Down Expand Up @@ -793,7 +795,7 @@ func (r *treeGeneratorImpl_v9_v10) processAttestationsBalancesAndWithdrawalsForI
}

// Check all of the attestations for each epoch
r.log.Printlnf("%s Checking participation of %d minipools for epochs %d to %d", r.logPrefix, len(r.validatorIndexMap), startEpoch, endEpoch)
r.log.Printlnf("%s Checking participation of %d minipools for epochs %d to %d", r.logPrefix, r.validatorIndexMap.Size(), startEpoch, endEpoch)
r.log.Printlnf("%s NOTE: this will take a long time, progress is reported every 100 epochs", r.logPrefix)

epochsDone := 0
Expand Down Expand Up @@ -863,12 +865,17 @@ func (r *treeGeneratorImpl_v9_v10) processEpoch(duringInterval bool, epoch uint6
}

for _, withdrawal := range beaconBlock.Withdrawals {
// Convert the validator index to an int
validatorIndex, err := strconv.Atoi(withdrawal.ValidatorIndex)
if err != nil {
return fmt.Errorf("error converting validator index to int: %w", err)
}
// Ignore non-RP validators
mpi, exists := r.validatorIndexMap[withdrawal.ValidatorIndex]
mpi, exists := r.validatorIndexMap.Get(validatorIndex)
if !exists {
continue
}
nnd := r.networkState.NodeDetailsByAddress[mpi.NodeAddress]
nnd := r.networkState.NodeDetailsByAddress[mpi.node.Address]
nmd := r.networkState.MinipoolDetailsByAddress[mpi.Address]

// Check that the node is opted into the SP during this slot
Expand Down Expand Up @@ -971,14 +978,13 @@ func (r *treeGeneratorImpl_v9_v10) checkAttestations(attestations []beacon.Attes
delete(validator.MissingAttestationSlots, attestation.SlotIndex)

// Check if this minipool was opted into the SP for this block
nodeDetails := r.nodeDetails[validator.NodeIndex]
if blockTime.Before(nodeDetails.OptInTime) || blockTime.After(nodeDetails.OptOutTime) {
if !validator.node.OptedInAt(blockTime) {
// Not opted in
continue
}

eligibleBorrowedEth := nodeDetails.EligibleBorrowedEth
_, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nodeDetails.RplStake)
eligibleBorrowedEth := validator.node.EligibleBorrowedEth
_, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, validator.node.RplStake)

// Mark this duty as completed
validator.CompletedAttestations[attestation.SlotIndex] = true
Expand Down Expand Up @@ -1023,25 +1029,23 @@ func (r *treeGeneratorImpl_v9_v10) getDutiesForEpoch(committees beacon.Committee
// Check if there are any RP validators in this committee
rpValidators := map[int]*MinipoolInfo{}
for position, validator := range committees.Validators(idx) {
minipoolInfo, exists := r.validatorIndexMap[validator]
validatorInt, err := strconv.Atoi(validator)
if err != nil {
return fmt.Errorf("error converting validator index to int: %w", err)
}
minipoolInfo, exists := r.validatorIndexMap.Get(validatorInt)
if !exists {
// This isn't an RP validator, so ignore it
continue
}

// Check if this minipool was opted into the SP for this block
nodeDetails := r.networkState.NodeDetailsByAddress[minipoolInfo.NodeAddress]
isOptedIn := nodeDetails.SmoothingPoolRegistrationState
spRegistrationTime := time.Unix(nodeDetails.SmoothingPoolRegistrationChanged.Int64(), 0)
if (isOptedIn && blockTime.Sub(spRegistrationTime) < 0) || // If this block occurred before the node opted in, ignore it
(!isOptedIn && spRegistrationTime.Sub(blockTime) < 0) { // If this block occurred after the node opted out, ignore it
if !minipoolInfo.node.OptedInAt(blockTime) {
continue
}

// Check if this minipool was in the `staking` state during this time
mpd := r.networkState.MinipoolDetailsByAddress[minipoolInfo.Address]
statusChangeTime := time.Unix(mpd.StatusTime.Int64(), 0)
if mpd.Status != rptypes.Staking || blockTime.Sub(statusChangeTime) < 0 {
if minipoolInfo.status != rptypes.Staking || blockTime.Sub(minipoolInfo.statusChangeTime) < 0 {
continue
}

Expand Down Expand Up @@ -1075,7 +1079,6 @@ func (r *treeGeneratorImpl_v9_v10) getDutiesForEpoch(committees beacon.Committee
func (r *treeGeneratorImpl_v9_v10) createMinipoolIndexMap() error {

// Get the status for all uncached minipool validators and add them to the cache
r.validatorIndexMap = map[string]*MinipoolInfo{}
for _, details := range r.nodeDetails {
if details.IsEligible {
for _, minipoolInfo := range details.Minipools {
Expand All @@ -1093,7 +1096,12 @@ func (r *treeGeneratorImpl_v9_v10) createMinipoolIndexMap() error {
default:
// Get the validator index
minipoolInfo.ValidatorIndex = status.Index
r.validatorIndexMap[minipoolInfo.ValidatorIndex] = minipoolInfo
// Convert the validator index to an int
validatorIndex, err := strconv.Atoi(minipoolInfo.ValidatorIndex)
if err != nil {
return fmt.Errorf("error converting validator index to int: %w", err)
}
r.validatorIndexMap.Add(validatorIndex, minipoolInfo)

// Get the validator's activation start and end slots
startSlot := status.ActivationEpoch * r.beaconConfig.SlotsPerEpoch
Expand Down Expand Up @@ -1163,13 +1171,7 @@ func (r *treeGeneratorImpl_v9_v10) getSmoothingPoolNodeDetails() error {
statusChangeTimeBig := nativeNodeDetails.SmoothingPoolRegistrationChanged
statusChangeTime := time.Unix(statusChangeTimeBig.Int64(), 0)

if nodeDetails.IsOptedIn {
nodeDetails.OptInTime = statusChangeTime
nodeDetails.OptOutTime = time.Unix(farFutureTimestamp, 0)
} else {
nodeDetails.OptOutTime = statusChangeTime
nodeDetails.OptInTime = time.Unix(farPastTimestamp, 0)
}
nodeDetails.SPRegistrationTime = statusChangeTime

// Get the details for each minipool in the node
for _, mpd := range r.networkState.MinipoolDetailsByNode[nodeDetails.Address] {
Expand Down Expand Up @@ -1198,6 +1200,10 @@ func (r *treeGeneratorImpl_v9_v10) getSmoothingPoolNodeDetails() error {
WasActive: true,
AttestationScore: NewQuotedBigInt(0),
NodeOperatorBond: nativeMinipoolDetails.NodeDepositBalance,

node: nodeDetails,
statusChangeTime: time.Unix(nativeMinipoolDetails.StatusTime.Int64(), 0),
status: nativeMinipoolDetails.Status,
})
}
}
Expand Down
21 changes: 19 additions & 2 deletions shared/services/rewards/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/rocket-pool/rocketpool-go/rewards"
"github.com/rocket-pool/rocketpool-go/types"
rptypes "github.com/rocket-pool/rocketpool-go/types"
"github.com/rocket-pool/smartnode/shared/services/beacon"
"github.com/wealdtech/go-merkletree"
)
Expand Down Expand Up @@ -224,6 +225,11 @@ type MinipoolInfo struct {
MinipoolBonus *big.Int `json:"-"`
NodeOperatorBond *big.Int `json:"-"`
ConsensusIncome *QuotedBigInt `json:"consensusIncome"`

// Internals
node *NodeSmoothingDetails `json:"-"`
statusChangeTime time.Time `json:"-"`
status rptypes.MinipoolStatus `json:"-"`
}

var sixteenEth = big.NewInt(0).Mul(oneEth, big.NewInt(16))
Expand Down Expand Up @@ -257,15 +263,26 @@ type NodeSmoothingDetails struct {
RewardsNetwork uint64

// v2 Fields
OptInTime time.Time
OptOutTime time.Time
SPRegistrationTime time.Time

// v10 Fields
BonusEth *big.Int
EligibleBorrowedEth *big.Int
RplStake *big.Int
}

func (node *NodeSmoothingDetails) OptedInAt(t time.Time) bool {
if node.IsOptedIn {
return t.After(node.SPRegistrationTime)
}
// _technically_ timestamps can be negative, but a node that never registered
// should not be eligible for rewards
if node.SPRegistrationTime.Unix() == 0 {
return false
}
return t.Before(node.SPRegistrationTime)
}

type QuotedBigInt struct {
big.Int
}
Expand Down

0 comments on commit 93a514d

Please sign in to comment.