Skip to content

Commit

Permalink
Merge pull request #11543 from vegaprotocol/11542
Browse files Browse the repository at this point in the history
fix: non determinism in lottery ranking fixed
  • Loading branch information
ze97286 authored Aug 8, 2024
2 parents 4205bf7 + 6779b49 commit 16e0325
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- [11521](https://github.com/vegaprotocol/vega/issues/11521) - Restore `AMM` position factor when loading from a snapshot.
- [11526](https://github.com/vegaprotocol/vega/issues/11526) - `EstimateAMMBounds` now respects the market's decimal places.
- [11540](https://github.com/vegaprotocol/vega/issues/11540) - Fix spam check for spots to use not double count quantum.
- [11542](https://github.com/vegaprotocol/vega/issues/11542) - Fix non determinism in lottery ranking.

## 0.77.5

Expand Down
24 changes: 13 additions & 11 deletions core/rewards/lottery_ranking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,18 @@ import (
)

func TestLotteryRewardScoreSorting(t *testing.T) {
adjustedRewardScores := []*types.PartyContributionScore{
{Party: "p1", Score: num.DecimalOne()},
{Party: "p2", Score: num.DecimalTwo()},
{Party: "p3", Score: num.DecimalFromFloat(0.01)},
}
const layout = "Jan 2, 2006 at 3:04pm"
for i := 0; i < 100; i++ {
adjustedRewardScores := []*types.PartyContributionScore{
{Party: "p1", Score: num.DecimalOne()},
{Party: "p2", Score: num.DecimalTwo()},
{Party: "p3", Score: num.DecimalFromFloat(0.01)},
}
const layout = "Jan 2, 2006 at 3:04pm"

timestamp, _ := time.Parse(layout, "Aug 7, 2024 at 12:00pm")
lottery := lotteryRewardScoreSorting(adjustedRewardScores, timestamp)
require.Equal(t, "p2", lottery[0].Party)
require.Equal(t, "p1", lottery[1].Party)
require.Equal(t, "p3", lottery[2].Party)
timestamp, _ := time.Parse(layout, "Aug 7, 2024 at 12:00pm")
lottery := lotteryRewardScoreSorting(adjustedRewardScores, timestamp)
require.Equal(t, "p2", lottery[0].Party)
require.Equal(t, "p1", lottery[1].Party)
require.Equal(t, "p3", lottery[2].Party)
}
}
29 changes: 25 additions & 4 deletions core/rewards/reward_distribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ func selectIndex(rng *rand.Rand, probabilities []num.Decimal) int {
return len(probabilities) - 1
}

type PartyProbability struct {
Probability num.Decimal
Party string
}

func lotteryRewardScoreSorting(adjustedPartyScores []*types.PartyContributionScore, timestamp time.Time) []*types.PartyContributionScore {
source := rand.NewSource(uint64(timestamp.UnixNano()))
rng := rand.New(source)
Expand All @@ -148,12 +153,28 @@ func lotteryRewardScoreSorting(adjustedPartyScores []*types.PartyContributionSco
if len(unselectedParties) < 1 {
break
}
probabilities := make([]num.Decimal, 0, len(unselectedParties))
parties := make([]string, 0, len(unselectedParties))
pp := make([]PartyProbability, 0, len(unselectedParties))
for _, ps := range unselectedParties {
probabilities = append(probabilities, ps.Score.Div(totalScores))
parties = append(parties, ps.Party)
pp = append(pp, PartyProbability{
Probability: ps.Score.Div(totalScores),
Party: ps.Party,
})
}
sort.Slice(pp, func(i, j int) bool {
if pp[i].Probability.Equal(pp[j].Probability) {
return pp[i].Party < pp[j].Party
}
return pp[i].Probability.LessThan(pp[j].Probability)
})

probabilities := make([]num.Decimal, len(pp))
parties := make([]string, len(pp))

for i, partyProb := range pp {
probabilities[i] = partyProb.Probability
parties[i] = partyProb.Party
}

selected := selectIndex(rng, probabilities)
selectedParty := unselectedParties[parties[selected]]
delete(unselectedParties, selectedParty.Party)
Expand Down

0 comments on commit 16e0325

Please sign in to comment.