-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(group): Update TresholdDecisionPolicy to handle threshold>totalWeight
#11325
Changes from 4 commits
23abb80
f236562
3ff9cbd
a7b3455
8077709
77dde44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,14 +74,23 @@ func (p ThresholdDecisionPolicy) Allow(tallyResult TallyResult, totalPower strin | |
if err != nil { | ||
return DecisionPolicyResult{}, err | ||
} | ||
if yesCount.Cmp(threshold) >= 0 { | ||
return DecisionPolicyResult{Allow: true, Final: true}, nil | ||
} | ||
|
||
totalPowerDec, err := math.NewNonNegativeDecFromString(totalPower) | ||
if err != nil { | ||
return DecisionPolicyResult{}, err | ||
} | ||
|
||
// the real threshold of the policy is `min(threshold,total_weight)`. If | ||
// the group member weights changes (member leaving, member weight update) | ||
// and the threshold doesn't, we can end up with threshold > total_weight. | ||
// In this case, as long as everyone votes yes (in which case | ||
// `yesCount`==`realThreshold`), then the proposal still passes. | ||
realThreshold := min(threshold, totalPowerDec) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AmauryM here can we just check if everyone voted yes instead of checking against realThreshold? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. There are 2 scenarios:
In the 2nd cases, we don't check everyone voted yes. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes. I don't have a strong preference now. Let's go with this unless anyone are strongly in favor of checking all-yes-votes for the special case. @blushi @robert-zaremba wdyt? |
||
|
||
if yesCount.Cmp(realThreshold) >= 0 { | ||
return DecisionPolicyResult{Allow: true, Final: true}, nil | ||
} | ||
|
||
totalCounts, err := tallyResult.TotalCounts() | ||
if err != nil { | ||
return DecisionPolicyResult{}, err | ||
|
@@ -90,29 +99,39 @@ func (p ThresholdDecisionPolicy) Allow(tallyResult TallyResult, totalPower strin | |
if err != nil { | ||
return DecisionPolicyResult{}, err | ||
} | ||
sum, err := yesCount.Add(undecided) | ||
// maxYesCount is the max number of yes count, i.e the current yes count | ||
amaury1093 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// plus all undecided count (supposing they all vote yes). | ||
maxYesCount, err := yesCount.Add(undecided) | ||
if err != nil { | ||
return DecisionPolicyResult{}, err | ||
} | ||
if sum.Cmp(threshold) < 0 { | ||
|
||
if maxYesCount.Cmp(realThreshold) < 0 { | ||
return DecisionPolicyResult{Allow: false, Final: true}, nil | ||
} | ||
return DecisionPolicyResult{Allow: false, Final: false}, nil | ||
} | ||
|
||
// Validate returns an error if policy threshold is greater than the total group weight | ||
func min(a, b math.Dec) math.Dec { | ||
if a.Cmp(b) < 0 { | ||
return a | ||
} | ||
return b | ||
} | ||
|
||
// Validate validates the policy against the group. Note that the threshold | ||
// can actually be greater than the group's total weight: in the Allow method | ||
// we check the tally weight against `min(threshold,total_weight)`. | ||
func (p *ThresholdDecisionPolicy) Validate(g GroupInfo, config Config) error { | ||
threshold, err := math.NewPositiveDecFromString(p.Threshold) | ||
_, err := math.NewPositiveDecFromString(p.Threshold) | ||
if err != nil { | ||
return sdkerrors.Wrap(err, "threshold") | ||
} | ||
totalWeight, err := math.NewNonNegativeDecFromString(g.TotalWeight) | ||
_, err = math.NewNonNegativeDecFromString(g.TotalWeight) | ||
if err != nil { | ||
return sdkerrors.Wrap(err, "group total weight") | ||
} | ||
if threshold.Cmp(totalWeight) > 0 { | ||
return sdkerrors.Wrapf(errors.ErrInvalid, "policy threshold %s should not be greater than the total group weight %s", p.Threshold, g.TotalWeight) | ||
} | ||
|
||
if p.Windows.MinExecutionPeriod > p.Windows.VotingPeriod+config.MaxExecutionPeriod { | ||
return sdkerrors.Wrap(errors.ErrInvalid, "min_execution_period should be smaller than voting_period + max_execution_period") | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm adding
DecisionPolicy.Validate()
calls in a few places in the msg server:anywhere else you think we need to add validation?