diff --git a/shared/services/beacon/client/std-http-client.go b/shared/services/beacon/client/std-http-client.go index ede174108..ad3ed1a50 100644 --- a/shared/services/beacon/client/std-http-client.go +++ b/shared/services/beacon/client/std-http-client.go @@ -650,6 +650,7 @@ func (c *StandardHttpClient) GetBeaconBlock(blockId string) (beacon.BeaconBlock, } // Add attestation info + beaconBlock.Attestations = make([]beacon.AttestationInfo, 0, len(block.Data.Message.Body.Attestations)) for i, attestation := range block.Data.Message.Body.Attestations { bitString := hexutil.RemovePrefix(attestation.AggregationBits) info := beacon.AttestationInfo{ @@ -664,6 +665,7 @@ func (c *StandardHttpClient) GetBeaconBlock(blockId string) (beacon.BeaconBlock, } // Add withdrawals + beaconBlock.Withdrawals = make([]beacon.WithdrawalInfo, 0, len(block.Data.Message.Body.ExecutionPayload.Withdrawals)) for _, withdrawal := range block.Data.Message.Body.ExecutionPayload.Withdrawals { amount, ok := new(big.Int).SetString(withdrawal.Amount, 10) if !ok { diff --git a/shared/services/rewards/generator-impl-v8-rolling.go b/shared/services/rewards/generator-impl-v8-rolling.go index aa4659363..d80a07179 100644 --- a/shared/services/rewards/generator-impl-v8-rolling.go +++ b/shared/services/rewards/generator-impl-v8-rolling.go @@ -707,10 +707,12 @@ func (r *treeGeneratorImpl_v8_rolling) calculateNodeRewards() (*big.Int, *big.In // Get the node amount nodeInfo, exists := r.nodeDetails[minipool.NodeAddress] if !exists { + nodeDetails := r.networkState.NodeDetailsByAddress[minipool.NodeAddress] nodeInfo = &NodeSmoothingDetails{ Minipools: []*MinipoolInfo{}, SmoothingPoolEth: big.NewInt(0), - RewardsNetwork: r.networkState.NodeDetailsByAddress[minipool.NodeAddress].RewardNetwork.Uint64(), + RewardsNetwork: nodeDetails.RewardNetwork.Uint64(), + RplStake: nodeDetails.RplStake, } r.nodeDetails[minipool.NodeAddress] = nodeInfo } diff --git a/shared/services/rewards/generator-impl-v8.go b/shared/services/rewards/generator-impl-v8.go index b59a00502..84384cd1f 100644 --- a/shared/services/rewards/generator-impl-v8.go +++ b/shared/services/rewards/generator-impl-v8.go @@ -1051,6 +1051,7 @@ func (r *treeGeneratorImpl_v8) getSmoothingPoolNodeDetails() error { Minipools: []*MinipoolInfo{}, SmoothingPoolEth: big.NewInt(0), RewardsNetwork: nativeNodeDetails.RewardNetwork.Uint64(), + RplStake: nativeNodeDetails.RplStake, } nodeDetails.IsOptedIn = nativeNodeDetails.SmoothingPoolRegistrationState @@ -1105,6 +1106,12 @@ func (r *treeGeneratorImpl_v8) getSmoothingPoolNodeDetails() error { } } + // Populate the eligible borrowed ETH field for all nodes + for _, nodeDetails := range r.nodeDetails { + nnd := r.networkState.NodeDetailsByAddress[nodeDetails.Address] + nodeDetails.EligibleBorrowedEth = r.networkState.GetEligibleBorrowedEth(nnd) + } + return nil } diff --git a/shared/services/rewards/generator-impl-v9-v10-rolling.go b/shared/services/rewards/generator-impl-v9-v10-rolling.go index 87741fa85..9a951e162 100644 --- a/shared/services/rewards/generator-impl-v9-v10-rolling.go +++ b/shared/services/rewards/generator-impl-v9-v10-rolling.go @@ -635,6 +635,7 @@ func (r *treeGeneratorImpl_v9_v10_rolling) calculateNodeRewards() (*big.Int, *bi SmoothingPoolEth: big.NewInt(0), BonusEth: big.NewInt(0), RewardsNetwork: nnd.RewardNetwork.Uint64(), + RplStake: nnd.RplStake, } nodeInfo.IsOptedIn = nnd.SmoothingPoolRegistrationState statusChangeTimeBig := nnd.SmoothingPoolRegistrationChanged @@ -687,6 +688,9 @@ func (r *treeGeneratorImpl_v9_v10_rolling) calculateNodeRewards() (*big.Int, *bi // Calculate the reduced bonus for each minipool // Because of integer division, this will be less than the actual bonus by up to 1 wei for _, mpd := range nsd.Minipools { + if mpd.MinipoolBonus == nil { + continue + } mpd.MinipoolBonus.Mul(mpd.MinipoolBonus, remainingBalance) mpd.MinipoolBonus.Div(mpd.MinipoolBonus, totalConsensusBonus) } diff --git a/shared/services/rewards/generator-impl-v9-v10.go b/shared/services/rewards/generator-impl-v9-v10.go index 02ef24346..5b9d332fe 100644 --- a/shared/services/rewards/generator-impl-v9-v10.go +++ b/shared/services/rewards/generator-impl-v9-v10.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" "sort" + "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -507,9 +508,8 @@ func (r *treeGeneratorImpl_v9_v10) calculateEthRewards(checkBeaconPerformance bo 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) { - nnd := r.networkState.NodeDetailsByAddress[nodeInfo.Address] - eligibleBorrowedEth := r.networkState.GetEligibleBorrowedEth(nnd) - _, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nnd.RplStake) + eligibleBorrowedEth := nodeInfo.EligibleBorrowedEth + _, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nodeInfo.RplStake) for _, minipool := range nodeInfo.Minipools { minipool.CompletedAttestations = map[uint64]bool{0: true} @@ -621,16 +621,15 @@ func (r *treeGeneratorImpl_v9_v10) calculateNodeBonuses() (*big.Int, error) { continue } - nnd := r.networkState.NodeDetailsByAddress[nsd.Address] - eligible, _, eligibleEnd := nnd.IsEligibleForBonuses(r.elStartTime, r.elEndTime) + nodeDetails := r.networkState.NodeDetailsByAddress[nsd.Address] + eligible, _, eligibleEnd := nodeDetails.IsEligibleForBonuses(r.elStartTime, r.elEndTime) if !eligible { continue } // Get the nodeDetails from the network state - nodeDetails := r.networkState.NodeDetailsByAddress[nsd.Address] - eligibleBorrowedEth := r.networkState.GetEligibleBorrowedEth(nodeDetails) - _, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nodeDetails.RplStake) + eligibleBorrowedEth := nsd.EligibleBorrowedEth + _, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nsd.RplStake) for _, mpd := range nsd.Minipools { mpi := r.networkState.MinipoolDetailsByAddress[mpd.Address] if !mpi.IsEligibleForBonuses(eligibleEnd) { @@ -739,6 +738,9 @@ func (r *treeGeneratorImpl_v9_v10) calculateNodeRewards() (*big.Int, *big.Int, * // Calculate the reduced bonus for each minipool // Because of integer division, this will be less than the actual bonus by up to 1 wei for _, mpd := range nsd.Minipools { + if mpd.MinipoolBonus == nil { + continue + } mpd.MinipoolBonus.Mul(mpd.MinipoolBonus, remainingBalance) mpd.MinipoolBonus.Div(mpd.MinipoolBonus, totalConsensusBonus) } @@ -839,6 +841,7 @@ func (r *treeGeneratorImpl_v9_v10) processEpoch(duringInterval bool, epoch uint6 }) } + withdrawalsLock := &sync.Mutex{} for i := uint64(0); i < r.slotsPerEpoch; i++ { // Get the beacon block for this slot i := i @@ -891,11 +894,13 @@ func (r *treeGeneratorImpl_v9_v10) processEpoch(duringInterval bool, epoch uint6 } // Create the minipool's withdrawal sum big.Int if it doesn't exist + withdrawalsLock.Lock() if r.minipoolWithdrawals[mpi.Address] == nil { r.minipoolWithdrawals[mpi.Address] = big.NewInt(0) } // Add the withdrawal amount r.minipoolWithdrawals[mpi.Address].Add(r.minipoolWithdrawals[mpi.Address], withdrawalAmount) + withdrawalsLock.Unlock() } return nil }) @@ -963,9 +968,8 @@ func (r *treeGeneratorImpl_v9_v10) checkAttestations(attestations []beacon.Attes continue } - nnd := r.networkState.NodeDetailsByAddress[validator.NodeAddress] - eligibleBorrowedEth := r.networkState.GetEligibleBorrowedEth(nnd) - _, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nnd.RplStake) + eligibleBorrowedEth := nodeDetails.EligibleBorrowedEth + _, percentOfBorrowedEth := r.networkState.GetStakedRplValueInEthAndPercentOfBorrowedEth(eligibleBorrowedEth, nodeDetails.RplStake) // Mark this duty as completed validator.CompletedAttestations[attestation.SlotIndex] = true @@ -1143,6 +1147,7 @@ func (r *treeGeneratorImpl_v9_v10) getSmoothingPoolNodeDetails() error { SmoothingPoolEth: big.NewInt(0), BonusEth: big.NewInt(0), RewardsNetwork: nativeNodeDetails.RewardNetwork.Uint64(), + RplStake: nativeNodeDetails.RplStake, } nodeDetails.IsOptedIn = nativeNodeDetails.SmoothingPoolRegistrationState @@ -1198,6 +1203,12 @@ func (r *treeGeneratorImpl_v9_v10) getSmoothingPoolNodeDetails() error { } } + // Populate the eligible borrowed ETH field for all nodes + for _, nodeDetails := range r.nodeDetails { + nnd := r.networkState.NodeDetailsByAddress[nodeDetails.Address] + nodeDetails.EligibleBorrowedEth = r.networkState.GetEligibleBorrowedEth(nnd) + } + return nil } diff --git a/shared/services/rewards/rolling-record.go b/shared/services/rewards/rolling-record.go index b23dd5af7..79d59da79 100644 --- a/shared/services/rewards/rolling-record.go +++ b/shared/services/rewards/rolling-record.go @@ -3,6 +3,7 @@ package rewards import ( "fmt" "math/big" + "sync" "time" "github.com/ethereum/go-ethereum/common" @@ -344,6 +345,7 @@ func (r *RollingRecord) processAttestationsInEpoch(epoch uint64, state *state.Ne attestationsPerSlot := make([][]beacon.AttestationInfo, r.beaconConfig.SlotsPerEpoch) // Get the attestation records for this epoch + withdrawalsLock := &sync.Mutex{} for i := uint64(0); i < slotsPerEpoch; i++ { i := i slot := epoch*slotsPerEpoch + i @@ -392,12 +394,14 @@ func (r *RollingRecord) processAttestationsInEpoch(epoch uint64, state *state.Ne } // Create the minipool's income big.Int if it doesn't exist + withdrawalsLock.Lock() if mpi.ConsensusIncome == nil { mpi.ConsensusIncome = NewQuotedBigInt(0) } // Add the withdrawal amount as consensus income mpi.ConsensusIncome.Add(&mpi.ConsensusIncome.Int, withdrawalAmount) + withdrawalsLock.Unlock() } } return nil diff --git a/shared/services/rewards/types.go b/shared/services/rewards/types.go index ffbed80ea..a2895c4b4 100644 --- a/shared/services/rewards/types.go +++ b/shared/services/rewards/types.go @@ -261,7 +261,9 @@ type NodeSmoothingDetails struct { OptOutTime time.Time // v10 Fields - BonusEth *big.Int + BonusEth *big.Int + EligibleBorrowedEth *big.Int + RplStake *big.Int } type QuotedBigInt struct {