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_test.go

146 lines
4.6 KiB

package votepower
import (
"math/big"
"math/rand"
"testing"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
)
var (
slotList shard.SlotList
totalStake numeric.Dec
harmonyNodes = 10
stakedNodes = 10
maxAccountGen = int64(98765654323123134)
accountGen = rand.New(rand.NewSource(1337))
maxKeyGen = int64(98765654323123134)
keyGen = rand.New(rand.NewSource(42))
maxStakeGen = int64(200)
stakeGen = rand.New(rand.NewSource(541))
)
func init() {
shard.Schedule = shardingconfig.LocalnetSchedule
for i := 0; i < harmonyNodes; i++ {
newSlot := generateRandomSlot()
newSlot.EffectiveStake = nil
slotList = append(slotList, newSlot)
}
totalStake = numeric.ZeroDec()
for j := 0; j < stakedNodes; j++ {
newSlot := generateRandomSlot()
totalStake = totalStake.Add(*newSlot.EffectiveStake)
slotList = append(slotList, newSlot)
}
}
func generateRandomSlot() shard.Slot {
addr := common.Address{}
addr.SetBytes(big.NewInt(int64(accountGen.Int63n(maxAccountGen))).Bytes())
secretKey := bls.SecretKey{}
secretKey.Deserialize(big.NewInt(int64(keyGen.Int63n(maxKeyGen))).Bytes())
key := shard.BlsPublicKey{}
key.FromLibBLSPublicKey(secretKey.GetPublicKey())
stake := numeric.NewDecFromBigInt(big.NewInt(int64(stakeGen.Int63n(maxStakeGen))))
return shard.Slot{addr, key, &stake}
}
func TestCompute(t *testing.T) {
expectedRoster := NewRoster(shard.BeaconChainShardID)
// Calculated when generated
expectedRoster.TotalEffectiveStake = totalStake
expectedRoster.HMYSlotCount = int64(harmonyNodes)
asDecHMYSlotCount := numeric.NewDec(expectedRoster.HMYSlotCount)
ourPercentage := numeric.ZeroDec()
theirPercentage := numeric.ZeroDec()
staked := slotList
for i := range staked {
member := AccommodateHarmonyVote{
PureStakedVote: PureStakedVote{
EarningAccount: staked[i].EcdsaAddress,
Identity: staked[i].BlsPublicKey,
GroupPercent: numeric.ZeroDec(),
EffectiveStake: numeric.ZeroDec(),
},
OverallPercent: numeric.ZeroDec(),
IsHarmonyNode: false,
}
// Real Staker
harmonyPercent := shard.Schedule.InstanceForEpoch(big.NewInt(3)).HarmonyVotePercent()
externalPercent := shard.Schedule.InstanceForEpoch(big.NewInt(3)).ExternalVotePercent()
if e := staked[i].EffectiveStake; e != nil {
member.EffectiveStake = member.EffectiveStake.Add(*e)
member.GroupPercent = e.Quo(expectedRoster.TotalEffectiveStake)
member.OverallPercent = member.GroupPercent.Mul(externalPercent)
theirPercentage = theirPercentage.Add(member.OverallPercent)
} else { // Our node
member.IsHarmonyNode = true
member.OverallPercent = harmonyPercent.Quo(asDecHMYSlotCount)
member.GroupPercent = member.OverallPercent.Quo(harmonyPercent)
ourPercentage = ourPercentage.Add(member.OverallPercent)
}
expectedRoster.Voters[staked[i].BlsPublicKey] = &member
}
expectedRoster.OurVotingPowerTotalPercentage = ourPercentage
expectedRoster.TheirVotingPowerTotalPercentage = theirPercentage
computedRoster, err := Compute(&shard.Committee{
shard.BeaconChainShardID, slotList,
}, big.NewInt(3))
if err != nil {
t.Error("Computed Roster failed on vote summation to one")
}
if !compareRosters(expectedRoster, computedRoster, t) {
t.Errorf("Compute Roster mismatch with expected Roster")
}
// Check that voting percents sum to 100
if !computedRoster.OurVotingPowerTotalPercentage.Add(
computedRoster.TheirVotingPowerTotalPercentage,
).Equal(numeric.OneDec()) {
t.Errorf(
"Total voting power does not equal 1. Harmony voting power: %s, Staked voting power: %s",
computedRoster.OurVotingPowerTotalPercentage,
computedRoster.TheirVotingPowerTotalPercentage,
)
}
}
func compareRosters(a, b *Roster, t *testing.T) bool {
voterMatch := true
for k, voter := range a.Voters {
if other, exists := b.Voters[k]; exists {
if !compareStakedVoter(voter, other) {
t.Error("voter slot not match")
voterMatch = false
}
} else {
t.Error("computed roster missing")
voterMatch = false
}
}
return a.OurVotingPowerTotalPercentage.Equal(b.OurVotingPowerTotalPercentage) &&
a.TheirVotingPowerTotalPercentage.Equal(b.TheirVotingPowerTotalPercentage) &&
a.TotalEffectiveStake.Equal(b.TotalEffectiveStake) &&
a.HMYSlotCount == b.HMYSlotCount && voterMatch
}
func compareStakedVoter(a, b *AccommodateHarmonyVote) bool {
return a.IsHarmonyNode == b.IsHarmonyNode &&
a.EarningAccount == b.EarningAccount &&
a.OverallPercent.Equal(b.OverallPercent) &&
a.EffectiveStake.Equal(b.EffectiveStake)
}