mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-07 10:12:19 +00:00
103 lines
3.4 KiB
Go
103 lines
3.4 KiB
Go
package casper
|
|
|
|
import (
|
|
"math"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/params"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var log = logrus.WithField("prefix", "casper")
|
|
|
|
// CalculateRewards adjusts validators balances by applying rewards or penalties
|
|
// based on FFG incentive structure.
|
|
// FFG Rewards scheme rewards validator who have voted on blocks, and penalises those validators
|
|
// who are offline. The penalties are more severe the longer they are offline.
|
|
func CalculateRewards(
|
|
slot uint64,
|
|
voterIndices []uint32,
|
|
validators []*pb.ValidatorRecord,
|
|
dynasty uint64,
|
|
totalParticipatedDeposit uint64,
|
|
timeSinceFinality uint64) []*pb.ValidatorRecord {
|
|
totalDeposit := TotalActiveValidatorDeposit(dynasty, validators)
|
|
activeValidators := ActiveValidatorIndices(validators, dynasty)
|
|
rewardQuotient := uint64(rewardQuotient(dynasty, validators))
|
|
penaltyQuotient := uint64(quadraticPenaltyQuotient())
|
|
depositFactor := (totalParticipatedDeposit - totalDeposit) / totalDeposit
|
|
|
|
log.Debugf("Applying rewards and penalties for the validators for slot %d", slot)
|
|
if timeSinceFinality <= 2*params.CycleLength {
|
|
for _, validatorIndex := range activeValidators {
|
|
var voted bool
|
|
|
|
for _, voterIndex := range voterIndices {
|
|
if voterIndex == validatorIndex {
|
|
voted = true
|
|
balance := validators[validatorIndex].GetBalance()
|
|
newbalance := uint64(balance + (balance/rewardQuotient)*depositFactor)
|
|
validators[validatorIndex].Balance = newbalance
|
|
break
|
|
}
|
|
}
|
|
|
|
if !voted {
|
|
newBalance := validators[validatorIndex].GetBalance()
|
|
newBalance -= newBalance / rewardQuotient
|
|
validators[validatorIndex].Balance = newBalance
|
|
}
|
|
}
|
|
|
|
} else {
|
|
for _, validatorIndex := range activeValidators {
|
|
var voted bool
|
|
|
|
for _, voterIndex := range voterIndices {
|
|
if voterIndex == validatorIndex {
|
|
voted = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !voted {
|
|
newBalance := validators[validatorIndex].GetBalance()
|
|
newBalance -= newBalance/rewardQuotient + newBalance*timeSinceFinality/penaltyQuotient
|
|
validators[validatorIndex].Balance = newBalance
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return validators
|
|
}
|
|
|
|
// rewardQuotient returns the reward quotient for validators which will be used to
|
|
// reward validators for voting on blocks, or penalise them for being offline.
|
|
func rewardQuotient(dynasty uint64, validators []*pb.ValidatorRecord) uint64 {
|
|
totalDepositETH := TotalActiveValidatorDepositInEth(dynasty, validators)
|
|
return params.BaseRewardQuotient * uint64(math.Pow(float64(totalDepositETH), 0.5))
|
|
}
|
|
|
|
// SlotMaxInterestRate returns the interest rate for a validator in a slot, the interest
|
|
// rate is targeted for a compunded annual rate of 3.88%.
|
|
func SlotMaxInterestRate(dynasty uint64, validators []*pb.ValidatorRecord) float64 {
|
|
rewardQuotient := float64(rewardQuotient(dynasty, validators))
|
|
return 1 / rewardQuotient
|
|
}
|
|
|
|
// quadraticPenaltyQuotient is the quotient that will be used to apply penalties to offline
|
|
// validators.
|
|
func quadraticPenaltyQuotient() uint64 {
|
|
dropTimeFactor := float64(params.SqrtDropTime / params.SlotDuration)
|
|
return uint64(math.Pow(dropTimeFactor, 0.5))
|
|
}
|
|
|
|
// QuadraticPenalty returns the penalty that will be applied to an offline validator
|
|
// based on the number of slots that they are offline.
|
|
func QuadraticPenalty(numberOfSlots uint64) uint64 {
|
|
slotFactor := (numberOfSlots * numberOfSlots) / 2
|
|
penaltyQuotient := quadraticPenaltyQuotient()
|
|
return slotFactor / uint64(penaltyQuotient)
|
|
}
|