Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions lib/pos_epoch_complete_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,24 +138,18 @@ func (bav *UtxoView) RunEpochCompleteHook(blockHeight uint64) error {
return errors.Wrapf(err, "RunEpochCompleteHook: problem retrieving SnapshotGlobalParamsEntry: ")
}

utxoOps := []*UtxoOperation{}

// Jail all inactive validators from the current snapshot validator set. This is an O(n) operation
// that loops through all validators and jails them if they are inactive. A jailed validator should be
// considered jailed in the next epoch we are transition into.
//
// TODO: Return UtxoOps for jailing validators.
if err = bav.JailAllInactiveValidators(blockHeight); err != nil {
return errors.Wrapf(err, "RunEpochCompleteHook: problem jailing all inactive validators: ")
}

// Reward all snapshotted stakes from the current snapshot validator set. This is an O(n) operation
// that loops through all of the snapshotted stakes and rewards them.
stakeDistributionUtxoOps, err := bav.DistributeStakingRewardsToSnapshotStakes()
if err != nil {
if err = bav.DistributeStakingRewardsToSnapshotStakes(blockHeight); err != nil {
return errors.Wrapf(err, "RunEpochCompleteHook: problem rewarding snapshot stakes: ")
}
utxoOps = append(utxoOps, stakeDistributionUtxoOps...)

// Calculate the NextEpochFinalBlockHeight.
nextEpochFinalBlockHeight, err := SafeUint64().Add(blockHeight, snapshotGlobalParamsEntry.EpochDurationNumBlocks)
Expand Down
45 changes: 16 additions & 29 deletions lib/pos_staking_rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,36 @@ import (
"github.com/pkg/errors"
)

func (bav *UtxoView) DistributeStakingRewardsToSnapshotStakes() ([]*UtxoOperation, error) {
func (bav *UtxoView) DistributeStakingRewardsToSnapshotStakes(blockHeight uint64) error {
// Check if we have switched from PoW to PoS yet. If we have not, then the PoS consensus
// has not started yet. We don't want to distribute any staking rewards until the PoS consensus begins.
if blockHeight < uint64(bav.Params.ForkHeights.ProofOfStake2ConsensusCutoverBlockHeight) {
return nil
}

// Retrieve the SnapshotGlobalParamsEntry.
snapshotGlobalParamsEntry, err := bav.GetSnapshotGlobalParamsEntry()
if err != nil {
return nil, errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem retrieving SnapshotGlobalParamsEntry: ")
return errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem retrieving SnapshotGlobalParamsEntry: ")
}

totalStakingRewards := bav._placeholderGetStakingRewardsPerEpoch()

// If the total rewards to pay out are zero, then there's nothing to be done. Exit early here.
if totalStakingRewards.IsZero() {
return nil, nil
return nil
}

// Reward all snapshotted stakes from the current snapshot validator set. This is an O(n) operation
// that loops through all of the snapshotted stakes and rewards them.
snapshotStakesToReward, err := bav.GetSnapshotStakesToRewardByStakeAmount(snapshotGlobalParamsEntry.StakingRewardsMaxNumStakes)
if err != nil {
return nil, errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem retrieving snapshot stakes to reward: ")
return errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem retrieving snapshot stakes to reward: ")
}

// If there are no stakes to reward, then there's nothing to be done. Exit early here.
if len(snapshotStakesToReward) == 0 {
return nil, nil
return nil
}

// Compute the total stake amount of all snapshot stakes, so we can determine the proportion of each
Expand All @@ -42,14 +48,9 @@ func (bav *UtxoView) DistributeStakingRewardsToSnapshotStakes() ([]*UtxoOperatio
// possible for a staker to stake zero DESO. We check it here to make this code more resilient, in case
// that assumption ever changes elsewhere in the codebase.
if snapshotStakesTotalStakeAmount.IsZero() {
return nil, nil
return nil
}

// Create a list of UtxoOperations to return. This will be populated with all of the operations in which
// we distributed rewards to stakers.
utxoOps := []*UtxoOperation{}
prevStakeEntries := []*StakeEntry{}

// Loop through all of the snapshot stakes and reward them.
for _, snapshotStakeEntry := range snapshotStakesToReward {
rewardAmount := _computeStakingRewardAmount(
Expand All @@ -68,7 +69,7 @@ func (bav *UtxoView) DistributeStakingRewardsToSnapshotStakes() ([]*UtxoOperatio
// Fetch the staker's latest StakeEntry.
stakeEntry, err := bav.GetStakeEntry(snapshotStakeEntry.ValidatorPKID, snapshotStakeEntry.StakerPKID)
if err != nil {
return nil, errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem fetching staker's StakeEntry: ")
return errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem fetching staker's StakeEntry: ")
}

// At this point, there are three possible cases:
Expand All @@ -79,8 +80,6 @@ func (bav *UtxoView) DistributeStakingRewardsToSnapshotStakes() ([]*UtxoOperatio

// For case 1, we distribute the rewards by adding them to the staker's staked amount.
if stakeEntry != nil && stakeEntry.RestakeRewards {
prevStakeEntries = append(prevStakeEntries, stakeEntry.Copy())

stakeEntry.StakeAmountNanos.Add(stakeEntry.StakeAmountNanos, rewardAmount)
bav._setStakeEntryMappings(stakeEntry)

Expand All @@ -92,24 +91,12 @@ func (bav *UtxoView) DistributeStakingRewardsToSnapshotStakes() ([]*UtxoOperatio
// set for the snapshot epoch. Their stake at the time was used to secure the network.

stakerPublicKey := bav.GetPublicKeyForPKID(snapshotStakeEntry.StakerPKID)

utxoOp, err := bav._addBalance(rewardAmount.Uint64(), stakerPublicKey)
if err != nil {
return nil, errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem adding rewards to staker's DESO balance: ")
if _, err = bav._addBalance(rewardAmount.Uint64(), stakerPublicKey); err != nil {
return errors.Wrapf(err, "DistributeStakingRewardsToSnapshotStakes: problem adding rewards to staker's DESO balance: ")
}

utxoOps = append(utxoOps, utxoOp)
}

// Merge all UtxoOps. The order doesn't matter here since the total reward distribution per staker
// is independent of the order in which the stakes are processed.
prevStakeEntriesUtxoOp := &UtxoOperation{
Type: OperationTypeStake,
PrevStakeEntries: prevStakeEntries,
}
utxoOps = append(utxoOps, prevStakeEntriesUtxoOp)

return utxoOps, nil
return nil
}

// This function is a placeholder that rewards a constant 10 DESO in staking rewards per epoch.
Expand Down