The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
woop/consensus/votepower/roster.go

123 lines
3.5 KiB

package votepower
import (
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
"github.com/pkg/errors"
)
var (
// HarmonysShare ..
HarmonysShare = numeric.MustNewDecFromStr("0.68")
// StakersShare ..
StakersShare = numeric.MustNewDecFromStr("0.32")
// ErrVotingPowerNotEqualOne ..
ErrVotingPowerNotEqualOne = errors.New("voting power not equal to one")
)
type stakedVoter struct {
IsActive, IsHarmonyNode bool
EarningAccount common.Address
Identity shard.BlsPublicKey
EffectivePercent numeric.Dec
RawStake numeric.Dec
}
// Roster ..
type Roster struct {
Voters map[shard.BlsPublicKey]stakedVoter
OurVotingPowerTotalPercentage numeric.Dec
TheirVotingPowerTotalPercentage numeric.Dec
RawStakedTotal numeric.Dec
HmySlotCount int64
}
// Compute creates a new roster based off the shard.SlotList
func Compute(staked shard.SlotList) (*Roster, error) {
roster := NewRoster()
for i := range staked {
if staked[i].TotalStake == nil {
roster.HmySlotCount++
} else {
roster.RawStakedTotal = roster.RawStakedTotal.Add(
*staked[i].TotalStake,
)
}
}
ourCount := numeric.NewDec(roster.HmySlotCount)
ourPercentage := numeric.ZeroDec()
theirPercentage := numeric.ZeroDec()
var lastStakedVoter *stakedVoter = nil
for i := range staked {
member := stakedVoter{
IsActive: true,
IsHarmonyNode: true,
EarningAccount: staked[i].EcdsaAddress,
Identity: staked[i].BlsPublicKey,
EffectivePercent: numeric.ZeroDec(),
RawStake: numeric.ZeroDec(),
}
// Real Staker
if staked[i].TotalStake != nil {
member.IsHarmonyNode = false
member.RawStake = member.RawStake.Add(*staked[i].TotalStake)
member.EffectivePercent = staked[i].TotalStake.
Quo(roster.RawStakedTotal).
Mul(StakersShare)
theirPercentage = theirPercentage.Add(member.EffectivePercent)
lastStakedVoter = &member
} else { // Our node
// TODO See the todo on where this called in one-node-staked-vote,
// need to have these two values of our
// percentage and hmy percentage sum to 1
member.EffectivePercent = HarmonysShare.Quo(ourCount)
ourPercentage = ourPercentage.Add(member.EffectivePercent)
}
roster.Voters[staked[i].BlsPublicKey] = member
}
// NOTE Enforce voting power sums to one, give diff (expect tiny amt) to last staked voter
if diff := numeric.OneDec().Sub(
ourPercentage.Add(theirPercentage),
); lastStakedVoter != nil {
lastStakedVoter.EffectivePercent = lastStakedVoter.EffectivePercent.Add(diff)
theirPercentage = theirPercentage.Add(diff)
utils.Logger().Info().
Str("diff", diff.String()).
Str("bls-public-key-of-receipent", lastStakedVoter.Identity.Hex()).
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.TheirVotingPowerTotalPercentage = theirPercentage
return roster, nil
}
// NewRoster ..
func NewRoster() *Roster {
return &Roster{
map[shard.BlsPublicKey]stakedVoter{},
numeric.ZeroDec(),
numeric.ZeroDec(),
numeric.ZeroDec(),
0,
}
}