Skip to content

Commit

Permalink
Added tests for reward distribution between participants and tasks (#186
Browse files Browse the repository at this point in the history
)

Added 2 tests:

On the participants' rewards distribution level: If more reputers have
the same totalReputerRewards to share, there will be fewer rewards for
each reputers.
On the task rewards distribution level: If there are more reputers, a
higher share of the total rewards will be allocated to reputers.
  • Loading branch information
guilherme-brandao authored Apr 24, 2024
1 parent 5d10002 commit 3d2fe44
Show file tree
Hide file tree
Showing 4 changed files with 460 additions and 117 deletions.
90 changes: 87 additions & 3 deletions x/emissions/module/rewards/reputer_rewards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@ func (s *RewardsTestSuite) TestGetReputersRewards() {
topidId := uint64(1)
block := int64(1003)

reputerAddrs := []sdk.AccAddress{
s.addrs[0],
s.addrs[1],
s.addrs[2],
s.addrs[3],
s.addrs[4],
}

// Generate reputers data for tests
_, err := mockReputersData(s, topidId, block)
_, err := mockReputersData(s, topidId, block, reputerAddrs)
s.Require().NoError(err)

// Get reputer rewards
Expand Down Expand Up @@ -46,8 +54,11 @@ func (s *RewardsTestSuite) TestGetReputersRewards() {
}
}

// mockReputersData generates reputer scores, stakes and losses
func mockReputersData(s *RewardsTestSuite, topicId uint64, block int64) (types.ReputerValueBundles, error) {
// After removing the number of reputers, the rewards should increase for the remaining reputers
func (s *RewardsTestSuite) TestGetReputersRewardsShouldIncreaseRewardsAfterRemovingReputer() {
topidId := uint64(1)
block := int64(1003)

reputerAddrs := []sdk.AccAddress{
s.addrs[0],
s.addrs[1],
Expand All @@ -56,6 +67,79 @@ func mockReputersData(s *RewardsTestSuite, topicId uint64, block int64) (types.R
s.addrs[4],
}

// Generate reputers data for tests
_, err := mockReputersData(s, topidId, block, reputerAddrs)
s.Require().NoError(err)

// Get reputer rewards
reputerRewards, err := rewards.GetReputerRewards(
s.ctx,
s.emissionsKeeper,
topidId,
block,
alloraMath.OneDec(),
alloraMath.MustNewDecFromString("1017.5559072418691"),
)
s.Require().NoError(err)
s.Require().Equal(5, len(reputerRewards))

expectedRewards := []alloraMath.Dec{
alloraMath.MustNewDecFromString("456.49"),
alloraMath.MustNewDecFromString("172.71"),
alloraMath.MustNewDecFromString("211.93"),
alloraMath.MustNewDecFromString("52.31"),
alloraMath.MustNewDecFromString("124.10"),
}

for i, reputerReward := range reputerRewards {
s.Require().True(
alloraMath.InDelta(expectedRewards[i], reputerReward.Reward, alloraMath.MustNewDecFromString("0.01")),
"expected: %s, got: %s",
expectedRewards[i].String(),
reputerReward.Reward.String(),
)
}

// New Topic, block and reputer addresses
topidId = uint64(2)
block = int64(1004)
// Reduce number of reputer addresses
reputerAddrs = []sdk.AccAddress{
s.addrs[5],
s.addrs[6],
s.addrs[7],
s.addrs[8],
}

// Generate reputers same loss data for less reputers
_, err = mockReputersData(s, topidId, block, reputerAddrs)
s.Require().NoError(err)

// Get reputer rewards
newReputerRewards, err := rewards.GetReputerRewards(
s.ctx,
s.emissionsKeeper,
topidId,
block,
alloraMath.OneDec(),
alloraMath.MustNewDecFromString("1017.5559072418691"),
)
s.Require().NoError(err)
s.Require().Equal(4, len(newReputerRewards))

for i, newReputerReward := range newReputerRewards {
newReputerReward.Reward.Gt(reputerRewards[i].Reward)
s.Require().True(
newReputerReward.Reward.Gt(reputerRewards[i].Reward),
"expected: %s, got: %s",
newReputerReward.Reward.String(),
reputerRewards[i].Reward.String(),
)
}
}

// mockReputersData generates reputer scores, stakes and losses
func mockReputersData(s *RewardsTestSuite, topicId uint64, block int64, reputerAddrs []sdk.AccAddress) (types.ReputerValueBundles, error) {
var scores = []alloraMath.Dec{
alloraMath.MustNewDecFromString("17.53436"),
alloraMath.MustNewDecFromString("20.29489"),
Expand Down
227 changes: 124 additions & 103 deletions x/emissions/module/rewards/rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,82 +66,7 @@ func EmitRewards(ctx sdk.Context, k keeper.Keeper, activeTopics []*types.Topic)
continue
}

lossBundles, err := k.GetNetworkLossBundleAtBlock(ctx, topic.Id, topicRewardNonce)
if err != nil {
return err
}

// Get Entropy for each task
reputerEntropy, reputerFractions, reputers, err := GetReputerTaskEntropy(
ctx,
k,
topic.Id,
moduleParams.TaskRewardAlpha,
moduleParams.PRewardSpread,
moduleParams.BetaEntropy,
topicRewardNonce,
)
if err != nil {
return err
}
inferenceEntropy, inferenceFractions, workersInference, err := GetInferenceTaskEntropy(
ctx,
k,
topic.Id,
moduleParams.TaskRewardAlpha,
moduleParams.PRewardSpread,
moduleParams.BetaEntropy,
topicRewardNonce,
)
if err != nil {
return err
}
forecastingEntropy, forecastFractions, workersForecast, err := GetForecastingTaskEntropy(
ctx,
k,
topic.Id,
moduleParams.TaskRewardAlpha,
moduleParams.PRewardSpread,
moduleParams.BetaEntropy,
topicRewardNonce,
)
if err != nil {
return err
}

// Get Total Rewards for Reputation task
taskReputerReward, err := GetRewardForReputerTaskInTopic(
inferenceEntropy,
forecastingEntropy,
reputerEntropy,
topicRewards,
)
if err != nil {
return err
}
taskInferenceReward, err := GetRewardForInferenceTaskInTopic(
lossBundles.NaiveValue,
lossBundles.CombinedValue,
inferenceEntropy,
forecastingEntropy,
reputerEntropy,
topicRewards,
moduleParams.SigmoidA,
moduleParams.SigmoidB,
)
if err != nil {
return err
}
taskForecastingReward, err := GetRewardForForecastingTaskInTopic(
lossBundles.NaiveValue,
lossBundles.CombinedValue,
inferenceEntropy,
forecastingEntropy,
reputerEntropy,
topicRewards,
moduleParams.SigmoidA,
moduleParams.SigmoidB,
)
taskReputerReward, taskInferenceReward, taskForecastingReward, err := GenerateTasksRewards(ctx, k, topic.Id, topicRewards, topicRewardNonce, moduleParams)
if err != nil {
return err
}
Expand Down Expand Up @@ -195,17 +120,6 @@ func EmitRewards(ctx sdk.Context, k keeper.Keeper, activeTopics []*types.Topic)
if err != nil {
return err
}
SetPreviousRewardFractions(
ctx,
k,
topic.Id,
reputers,
reputerFractions,
workersInference,
inferenceFractions,
workersForecast,
forecastFractions,
)

// Delete topic reward nonce
err = k.DeleteTopicRewardNonce(ctx, topic.Id)
Expand All @@ -218,25 +132,111 @@ func EmitRewards(ctx sdk.Context, k keeper.Keeper, activeTopics []*types.Topic)
return nil
}

func payoutRewards(ctx sdk.Context, k keeper.Keeper, rewards []TaskRewards) error {
for _, reward := range rewards {
address, err := sdk.AccAddressFromBech32(reward.Address.String())
if err != nil {
return err
}
func GenerateTasksRewards(
ctx sdk.Context,
k keeper.Keeper,
topicId uint64,
topicRewards alloraMath.Dec,
block int64,
moduleParams types.Params,
) (
alloraMath.Dec,
alloraMath.Dec,
alloraMath.Dec,
error,
) {
lossBundles, err := k.GetNetworkLossBundleAtBlock(ctx, topicId, block)
if err != nil {
return alloraMath.Dec{}, alloraMath.Dec{}, alloraMath.Dec{}, err
}

err = k.BankKeeper().SendCoinsFromModuleToAccount(
ctx,
types.AlloraRewardsAccountName,
address,
sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, reward.Reward.SdkIntTrim())),
)
if err != nil {
return err
}
reputerEntropy, reputerFractions, reputers, err := GetReputerTaskEntropy(
ctx,
k,
topicId,
moduleParams.TaskRewardAlpha,
moduleParams.PRewardSpread,
moduleParams.BetaEntropy,
block,
)
if err != nil {
return alloraMath.Dec{}, alloraMath.Dec{}, alloraMath.Dec{}, err
}
inferenceEntropy, inferenceFractions, workersInference, err := GetInferenceTaskEntropy(
ctx,
k,
topicId,
moduleParams.TaskRewardAlpha,
moduleParams.PRewardSpread,
moduleParams.BetaEntropy,
block,
)
if err != nil {
return alloraMath.Dec{}, alloraMath.Dec{}, alloraMath.Dec{}, err
}
forecastingEntropy, forecastFractions, workersForecast, err := GetForecastingTaskEntropy(
ctx,
k,
topicId,
moduleParams.TaskRewardAlpha,
moduleParams.PRewardSpread,
moduleParams.BetaEntropy,
block,
)
if err != nil {
return alloraMath.Dec{}, alloraMath.Dec{}, alloraMath.Dec{}, err
}

return nil
// Get Total Rewards for Reputation task
taskReputerReward, err := GetRewardForReputerTaskInTopic(
inferenceEntropy,
forecastingEntropy,
reputerEntropy,
topicRewards,
)
if err != nil {
return alloraMath.Dec{}, alloraMath.Dec{}, alloraMath.Dec{}, err
}
taskInferenceReward, err := GetRewardForInferenceTaskInTopic(
lossBundles.NaiveValue,
lossBundles.CombinedValue,
inferenceEntropy,
forecastingEntropy,
reputerEntropy,
topicRewards,
moduleParams.SigmoidA,
moduleParams.SigmoidB,
)
if err != nil {
return alloraMath.Dec{}, alloraMath.Dec{}, alloraMath.Dec{}, err
}
taskForecastingReward, err := GetRewardForForecastingTaskInTopic(
lossBundles.NaiveValue,
lossBundles.CombinedValue,
inferenceEntropy,
forecastingEntropy,
reputerEntropy,
topicRewards,
moduleParams.SigmoidA,
moduleParams.SigmoidB,
)
if err != nil {
return alloraMath.Dec{}, alloraMath.Dec{}, alloraMath.Dec{}, err
}

SetPreviousRewardFractions(
ctx,
k,
topicId,
reputers,
reputerFractions,
workersInference,
inferenceFractions,
workersForecast,
forecastFractions,
)

return taskReputerReward, taskInferenceReward, taskForecastingReward, nil
}

func SetPreviousRewardFractions(
Expand Down Expand Up @@ -270,3 +270,24 @@ func SetPreviousRewardFractions(
}
return nil
}

func payoutRewards(ctx sdk.Context, k keeper.Keeper, rewards []TaskRewards) error {
for _, reward := range rewards {
address, err := sdk.AccAddressFromBech32(reward.Address.String())
if err != nil {
return err
}

err = k.BankKeeper().SendCoinsFromModuleToAccount(
ctx,
types.AlloraRewardsAccountName,
address,
sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, reward.Reward.SdkIntTrim())),
)
if err != nil {
return err
}
}

return nil
}
Loading

0 comments on commit 3d2fe44

Please sign in to comment.