[votepower] Allow negative diff, explicit check sum to one (#1930)

* [votepower] Allow negative diff, explicit check sum to one

* [votepower] Handle error value from compute in test

* [votepower] Change log as suggested in PR comment

* [votepower] Check sum of voting power is 1 only when have at least one staked validator
pull/1931/head
Edgar Aroutiounian 5 years ago committed by GitHub
parent 954c50a561
commit a8a9f7c951
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      consensus/quorum/one-node-staked-vote.go
  2. 18
      consensus/votepower/roster.go
  3. 6
      consensus/votepower/roster_test.go
  4. 10
      internal/chain/reward.go

@ -185,7 +185,10 @@ func (v *stakedVoteWeight) SetVoters(
s, _ := v.ShardIDProvider()() s, _ := v.ShardIDProvider()()
v.Reset([]Phase{Prepare, Commit, ViewChange}) v.Reset([]Phase{Prepare, Commit, ViewChange})
roster := votepower.Compute(staked) roster, err := votepower.Compute(staked)
if err != nil {
return nil, err
}
utils.Logger().Info(). utils.Logger().Info().
Str("our-percentage", roster.OurVotingPowerTotalPercentage.String()). Str("our-percentage", roster.OurVotingPowerTotalPercentage.String()).
Str("their-percentage", roster.TheirVotingPowerTotalPercentage.String()). Str("their-percentage", roster.TheirVotingPowerTotalPercentage.String()).

@ -5,6 +5,7 @@ import (
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
"github.com/pkg/errors"
) )
var ( var (
@ -12,6 +13,8 @@ var (
HarmonysShare = numeric.MustNewDecFromStr("0.68") HarmonysShare = numeric.MustNewDecFromStr("0.68")
// StakersShare .. // StakersShare ..
StakersShare = numeric.MustNewDecFromStr("0.32") StakersShare = numeric.MustNewDecFromStr("0.32")
// ErrVotingPowerNotEqualOne ..
ErrVotingPowerNotEqualOne = errors.New("voting power not equal to one")
) )
type stakedVoter struct { type stakedVoter struct {
@ -32,7 +35,7 @@ type Roster struct {
} }
// Compute creates a new roster based off the shard.SlotList // Compute creates a new roster based off the shard.SlotList
func Compute(staked shard.SlotList) *Roster { func Compute(staked shard.SlotList) (*Roster, error) {
roster := NewRoster() roster := NewRoster()
for i := range staked { for i := range staked {
if staked[i].TotalStake == nil { if staked[i].TotalStake == nil {
@ -82,7 +85,7 @@ func Compute(staked shard.SlotList) *Roster {
// NOTE Enforce voting power sums to one, give diff (expect tiny amt) to last staked voter // NOTE Enforce voting power sums to one, give diff (expect tiny amt) to last staked voter
if diff := numeric.OneDec().Sub( if diff := numeric.OneDec().Sub(
ourPercentage.Add(theirPercentage), ourPercentage.Add(theirPercentage),
); diff.GT(numeric.ZeroDec()) && lastStakedVoter != nil { ); lastStakedVoter != nil {
lastStakedVoter.EffectivePercent = lastStakedVoter.EffectivePercent.Add(diff) lastStakedVoter.EffectivePercent = lastStakedVoter.EffectivePercent.Add(diff)
theirPercentage = theirPercentage.Add(diff) theirPercentage = theirPercentage.Add(diff)
utils.Logger().Info(). utils.Logger().Info().
@ -91,10 +94,19 @@ func Compute(staked shard.SlotList) *Roster {
Msg("sum of voting power of hmy & staked slots not equal to 1, gave diff to staked slot") Msg("sum of voting power of hmy & staked slots not equal to 1, gave diff to staked slot")
} }
if lastStakedVoter != nil &&
!ourPercentage.Add(theirPercentage).Equal(numeric.OneDec()) {
utils.Logger().Error().
Str("theirs", theirPercentage.String()).
Str("ours", ourPercentage.String()).
Msg("Total voting power not equal 100 percent")
return nil, ErrVotingPowerNotEqualOne
}
roster.OurVotingPowerTotalPercentage = ourPercentage roster.OurVotingPowerTotalPercentage = ourPercentage
roster.TheirVotingPowerTotalPercentage = theirPercentage roster.TheirVotingPowerTotalPercentage = theirPercentage
return roster return roster, nil
} }

@ -81,7 +81,11 @@ func TestCompute(t *testing.T) {
expectedRoster.Voters[slot.BlsPublicKey] = newMember expectedRoster.Voters[slot.BlsPublicKey] = newMember
} }
computedRoster := Compute(slotList) computedRoster, err := Compute(slotList)
if err != nil {
t.Error("Computed Roster failed on vote summation to one")
}
if !compareRosters(expectedRoster, computedRoster, t) { if !compareRosters(expectedRoster, computedRoster, t) {
t.Errorf("Compute Roster mismatch with expected Roster") t.Errorf("Compute Roster mismatch with expected Roster")
} }

@ -219,7 +219,10 @@ func AccumulateRewards(
return err return err
} }
votingPower := votepower.Compute(members) votingPower, err := votepower.Compute(members)
if err != nil {
return err
}
for beaconMember := range payable { for beaconMember := range payable {
// TODO Give out whatever leftover to the last voter/handle // TODO Give out whatever leftover to the last voter/handle
@ -271,7 +274,10 @@ func AccumulateRewards(
return err return err
} }
votingPower := votepower.Compute(payableSigners) votingPower, err := votepower.Compute(payableSigners)
if err != nil {
return err
}
for j := range payableSigners { for j := range payableSigners {
voter := votingPower.Voters[payableSigners[j].BlsPublicKey] voter := votingPower.Voters[payableSigners[j].BlsPublicKey]
if !voter.IsHarmonyNode && !voter.EffectivePercent.IsZero() { if !voter.IsHarmonyNode && !voter.EffectivePercent.IsZero() {

Loading…
Cancel
Save