Skip to content

Commit

Permalink
add online, weak merit based sortition without new scores yet
Browse files Browse the repository at this point in the history
  • Loading branch information
kpeluso committed Aug 31, 2024
1 parent 9630dad commit 270042d
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 66 deletions.
132 changes: 132 additions & 0 deletions x/emissions/keeper/ema_scores.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package keeper

import (
"context"

"cosmossdk.io/errors"
alloraMath "github.com/allora-network/allora-chain/math"
"github.com/allora-network/allora-chain/x/emissions/types"
)

// Calculates and saves the EMA scores for a given worker and topic
// Does nothing if the last update of the score was topic.WorkerSubmissionWindow blocks ago or less
// This is useful to ensure workers cannot game the system by spamming submissions to unfairly up their score
func (k *Keeper) CalcAndSaveInfererScoreEmaIfNewUpdate(
ctx context.Context,
topic types.Topic,
block types.BlockHeight,
worker ActorId,
newScore types.Score,
) error {
previousScore, err := k.GetInfererScoreEma(ctx, topic.Id, worker)
if err != nil {
return errors.Wrapf(err, "Error getting inferer score ema")
}
// Only calc and save if there's a new update
if newScore.BlockHeight-previousScore.BlockHeight <= topic.WorkerSubmissionWindow {
return nil
}
firstTime := previousScore.BlockHeight == 0 && previousScore.Score.IsZero()
emaScoreDec, err := alloraMath.CalcEma(
topic.MeritSortitionAlpha,
newScore.Score,
previousScore.Score,
firstTime,
)
if err != nil {
return errors.Wrapf(err, "Error calculating ema")
}
emaScore := types.Score{
TopicId: topic.Id,
BlockHeight: block,
Address: worker,
Score: emaScoreDec,
}
err = k.SetInfererScoreEma(ctx, topic.Id, worker, emaScore)
if err != nil {
return errors.Wrapf(err, "error setting latest inferer score")
}
return nil
}

// Calculates and saves the EMA scores for a given worker and topic
// Does nothing if the last update of the score was topic.WorkerSubmissionWindow blocks ago or less
// This is useful to ensure workers cannot game the system by spamming submissions to unfairly up their score
func (k *Keeper) CalcAndSaveForecasterScoreEmaIfNewUpdate(
ctx context.Context,
topic types.Topic,
block types.BlockHeight,
worker ActorId,
newScore types.Score,
) error {
previousScore, err := k.GetForecasterScoreEma(ctx, topic.Id, worker)
if err != nil {
return errors.Wrapf(err, "Error getting forecaster score ema")
}
// Only calc and save if there's a new update
if newScore.BlockHeight-previousScore.BlockHeight <= topic.WorkerSubmissionWindow {
return nil
}
firstTime := previousScore.BlockHeight == 0 && previousScore.Score.IsZero()
emaScoreDec, err := alloraMath.CalcEma(
topic.MeritSortitionAlpha,
newScore.Score,
previousScore.Score,
firstTime,
)
if err != nil {
return errors.Wrapf(err, "Error calculating ema")
}
emaScore := types.Score{
TopicId: topic.Id,
BlockHeight: block,
Address: worker,
Score: emaScoreDec,
}
err = k.SetForecasterScoreEma(ctx, topic.Id, worker, emaScore)
if err != nil {
return errors.Wrapf(err, "error setting latest forecaster score")
}
return nil
}

// Calculates and saves the EMA scores for a given reputer and topic
// Does nothing if the last update of the score was topic.EpochLength blocks ago or less
// This is useful to ensure reputers cannot game the system by spamming submissions to unfairly up their score
func (k *Keeper) CalcAndSaveReputerScoreEmaIfNewUpdate(
ctx context.Context,
topic types.Topic,
block types.BlockHeight,
worker ActorId,
newScore types.Score,
) error {
previousScore, err := k.GetReputerScoreEma(ctx, topic.Id, worker)
if err != nil {
return errors.Wrapf(err, "Error getting reputer score ema")
}
// Only calc and save if there's a new update
if newScore.BlockHeight-previousScore.BlockHeight <= topic.EpochLength {
return nil
}
firstTime := previousScore.BlockHeight == 0 && previousScore.Score.IsZero()
emaScoreDec, err := alloraMath.CalcEma(
topic.MeritSortitionAlpha,
newScore.Score,
previousScore.Score,
firstTime,
)
if err != nil {
return errors.Wrapf(err, "Error calculating ema")
}
emaScore := types.Score{
TopicId: topic.Id,
BlockHeight: block,
Address: worker,
Score: emaScoreDec,
}
err = k.SetReputerScoreEma(ctx, topic.Id, worker, emaScore)
if err != nil {
return errors.Wrapf(err, "error setting latest reputer score")
}
return nil
}
36 changes: 36 additions & 0 deletions x/emissions/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,18 @@ func (k *Keeper) AppendInference(ctx context.Context, topicId TopicId, nonce typ
newInferences.Inferences = append(newInferences.Inferences[:lowScoreIndex], newInferences.Inferences[lowScoreIndex+1:]...)
newInferences.Inferences = append(newInferences.Inferences, inference)
return k.allInferences.Set(ctx, key, newInferences)
} else {
topic, err := k.GetTopic(ctx, topicId)
if err != nil {
return err
}
/*
* TODO: Get + use previous active set score!
*/
err = k.CalcAndSaveInfererScoreEmaIfNewUpdate(ctx, topic, block, inference.Inferer, score)
if err != nil {
return err
}
}
return nil
}
Expand Down Expand Up @@ -888,6 +900,18 @@ func (k *Keeper) AppendForecast(ctx context.Context, topicId TopicId, nonce type
newForecasts.Forecasts = append(newForecasts.Forecasts[:lowScoreIndex], newForecasts.Forecasts[lowScoreIndex+1:]...)
newForecasts.Forecasts = append(newForecasts.Forecasts, forecast)
return k.allForecasts.Set(ctx, key, newForecasts)
} else {
topic, err := k.GetTopic(ctx, topicId)
if err != nil {
return err
}
/*
* TODO: Get + use previous active set score!
*/
err = k.CalcAndSaveForecasterScoreEmaIfNewUpdate(ctx, topic, block, forecast.Forecaster, score)
if err != nil {
return err
}
}
return nil
}
Expand Down Expand Up @@ -989,6 +1013,18 @@ func (k *Keeper) AppendReputerLoss(ctx context.Context, topicId TopicId, block B
newReputerLossBundles.ReputerValueBundles[lowScoreIndex+1:]...)
newReputerLossBundles.ReputerValueBundles = append(newReputerLossBundles.ReputerValueBundles, reputerLoss)
return k.allLossBundles.Set(ctx, key, newReputerLossBundles)
} else {
topic, err := k.GetTopic(ctx, topicId)
if err != nil {
return err
}
/*
* TODO: Get + use previous active set score!
*/
err = k.CalcAndSaveReputerScoreEmaIfNewUpdate(ctx, topic, block, reputerLoss.ValueBundle.Reputer, score)
if err != nil {
return err
}
}
return nil
}
Expand Down
78 changes: 12 additions & 66 deletions x/emissions/module/rewards/scores.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,30 +108,12 @@ func GenerateReputerScores(
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error inserting reputer score")
}
previousScore, err := keeper.GetReputerScoreEma(ctx, topicId, reputer)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error getting reputer score ema")
}
firstTime := previousScore.BlockHeight == 0 && previousScore.Score.IsZero()
emaScoreDec, err := alloraMath.CalcEma(
topic.MeritSortitionAlpha,
newScore.Score,
previousScore.Score,
firstTime,
)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error calculating ema")
}
emaScore := types.Score{
TopicId: topicId,
BlockHeight: block,
Address: reputer,
Score: emaScoreDec,
}
err = keeper.SetReputerScoreEma(ctx, topicId, reputer, emaScore)

err = keeper.CalcAndSaveReputerScoreEmaIfNewUpdate(ctx, topic, block, reputer, newScore)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error setting latest reputer score")
return []types.Score{}, errors.Wrapf(err, "Error calculating and saving reputer score ema")
}

newScores = append(newScores, newScore)
}

Expand Down Expand Up @@ -186,30 +168,12 @@ func GenerateInferenceScores(
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error inserting worker inference score")
}
previousScore, err := keeper.GetInfererScoreEma(ctx, topicId, oneOutLoss.Worker)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error getting inferer score ema")
}
firstTime := previousScore.BlockHeight == 0 && previousScore.Score.IsZero()
emaScoreDec, err := alloraMath.CalcEma(
topic.MeritSortitionAlpha,
newScore.Score,
previousScore.Score,
firstTime,
)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error calculating ema")
}
emaScore := types.Score{
TopicId: topicId,
BlockHeight: block,
Address: oneOutLoss.Worker,
Score: emaScoreDec,
}
err = keeper.SetInfererScoreEma(ctx, topicId, oneOutLoss.Worker, emaScore)

err = keeper.CalcAndSaveInfererScoreEmaIfNewUpdate(ctx, topic, block, oneOutLoss.Worker, newScore)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "error setting latest inferer score")
return []types.Score{}, errors.Wrapf(err, "Error calculating and saving inferer score ema")
}

newScores = append(newScores, newScore)
}

Expand Down Expand Up @@ -288,30 +252,12 @@ func GenerateForecastScores(
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error inserting worker forecast score")
}
previousScore, err := keeper.GetForecasterScoreEma(ctx, topicId, oneInNaiveLoss.Worker)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error getting inferer score ema")
}
firstTime := previousScore.BlockHeight == 0 && previousScore.Score.IsZero()
emaScoreDec, err := alloraMath.CalcEma(
topic.MeritSortitionAlpha,
newScore.Score,
previousScore.Score,
firstTime,
)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error calculating ema")
}
emaScore := types.Score{
TopicId: topicId,
BlockHeight: block,
Address: oneInNaiveLoss.Worker,
Score: emaScoreDec,
}
err = keeper.SetForecasterScoreEma(ctx, topicId, oneInNaiveLoss.Worker, emaScore)

err = keeper.CalcAndSaveForecasterScoreEmaIfNewUpdate(ctx, topic, block, oneInNaiveLoss.Worker, newScore)
if err != nil {
return []types.Score{}, errors.Wrapf(err, "Error setting latest forecaster score")
return []types.Score{}, errors.Wrapf(err, "Error calculating and saving forecaster score ema")
}

newScores = append(newScores, newScore)
}

Expand Down

0 comments on commit 270042d

Please sign in to comment.