Move Get Cutoff Algo to Utils Package (#370)

This commit is contained in:
terence tsao
2018-08-02 14:20:54 -07:00
committed by GitHub
parent 0a5e091ad3
commit 87d5fbfd2b
4 changed files with 105 additions and 103 deletions

View File

@@ -270,52 +270,6 @@ func (b *BeaconChain) getAttestersProposer(seed common.Hash) ([]int, int, error)
return indices[:int(attesterCount)], indices[len(indices)-1], nil
}
// GetCutoffs is used to split up validators into groups at the start
// of every epoch. It determines at what height validators can make
// attestations and crosslinks. It returns lists of cutoff indices.
func GetCutoffs(validatorCount int) []int {
var heightCutoff = []int{0}
var heights []int
var heightCount float64
// Skip heights if there's not enough validators to fill in a min sized committee.
if validatorCount < params.EpochLength*params.MinCommiteeSize {
heightCount = math.Floor(float64(validatorCount) / params.MinCommiteeSize)
for i := 0; i < int(heightCount); i++ {
heights = append(heights, (i*params.Cofactor)%params.EpochLength)
}
// Enough validators, fill in all the heights.
} else {
heightCount = params.EpochLength
for i := 0; i < int(heightCount); i++ {
heights = append(heights, i)
}
}
filled := 0
appendHeight := false
for i := 0; i < params.EpochLength-1; i++ {
appendHeight = false
for _, height := range heights {
if i == height {
appendHeight = true
}
}
if appendHeight {
filled++
heightCutoff = append(heightCutoff, filled*validatorCount/int(heightCount))
} else {
heightCutoff = append(heightCutoff, heightCutoff[len(heightCutoff)-1])
}
}
heightCutoff = append(heightCutoff, validatorCount)
// TODO: For the validators assigned to each height, split them up into
// committees for different shards. Do not assign the last END_EPOCH_GRACE_PERIOD
// heights in a epoch to any shards.
return heightCutoff
}
// calculateRewardsFFG adjusts validators balances by applying rewards or penalties
// based on FFG incentive structure.
func (b *BeaconChain) calculateRewardsFFG() error {

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"context"
"errors"
"math"
"reflect"
"testing"
@@ -419,49 +418,6 @@ func TestRotateValidatorSet(t *testing.T) {
}
}
func TestCutOffValidatorSet(t *testing.T) {
// Test scenario #1: Assume there's enough validators to fill in all the heights.
validatorCount := params.EpochLength * params.MinCommiteeSize
cutoffsValidators := GetCutoffs(validatorCount)
// The length of cutoff list should be 65. Since there is 64 heights per epoch,
// it means during every height, a new set of 128 validators will form a committee.
expectedCount := int(math.Ceil(float64(validatorCount)/params.MinCommiteeSize)) + 1
if len(cutoffsValidators) != expectedCount {
t.Errorf("Incorrect count for cutoffs validator. Wanted: %v, Got: %v", expectedCount, len(cutoffsValidators))
}
// Verify each cutoff is an increment of MinCommiteeSize, it means 128 validators forms a
// a committee and get to attest per height.
count := 0
for _, cutoff := range cutoffsValidators {
if cutoff != count {
t.Errorf("cutoffsValidators did not get 128 increment. Wanted: count, Got: %v", cutoff)
}
count += params.MinCommiteeSize
}
// Test scenario #2: Assume there's not enough validators to fill in all the heights.
validatorCount = 1000
cutoffsValidators = unique(GetCutoffs(validatorCount))
// With 1000 validators, we can't attest every height. Given min committee size is 128,
// we can only attest 7 heights. round down 1000 / 128 equals to 7, means the length is 8.
expectedCount = int(math.Ceil(float64(validatorCount) / params.MinCommiteeSize))
if len(unique(cutoffsValidators)) != expectedCount {
t.Errorf("Incorrect count for cutoffs validator. Wanted: %v, Got: %v", expectedCount, validatorCount/params.MinCommiteeSize)
}
// Verify each cutoff is an increment of 142~143 (1000 / 7).
count = 0
for _, cutoff := range cutoffsValidators {
num := count * validatorCount / (len(cutoffsValidators) - 1)
if cutoff != num {
t.Errorf("cutoffsValidators did not get correct increment. Wanted: %v, Got: %v", num, cutoff)
}
count++
}
}
func TestIsEpochTransition(t *testing.T) {
beaconChain, db := startInMemoryBeaconChain(t)
defer db.Close()
@@ -658,19 +614,6 @@ func TestComputeValidatorRewardsAndPenalties(t *testing.T) {
}
}
// helper function to remove duplicates in a int slice.
func unique(ints []int) []int {
keys := make(map[int]bool)
list := []int{}
for _, int := range ints {
if _, value := keys[int]; !value {
keys[int] = true
list = append(list, int)
}
}
return list
}
// NewBlock is a helper method to create blocks with valid defaults.
// For a generic block, use NewBlock(t, nil)
func NewBlock(t *testing.T, b *pb.BeaconBlockResponse) *types.Block {

View File

@@ -2,6 +2,7 @@ package utils
import (
"errors"
"math"
"github.com/ethereum/go-ethereum/common"
"github.com/prysmaticlabs/prysm/beacon-chain/params"
@@ -35,3 +36,49 @@ func ShuffleIndices(seed common.Hash, validatorCount int) ([]int, error) {
}
return validatorList, nil
}
// GetCutoffs is used to split up validators into groups at the start
// of every epoch. It determines at what height validators can make
// attestations and crosslinks. It returns lists of cutoff indices.
func GetCutoffs(validatorCount int) []int {
var heightCutoff = []int{0}
var heights []int
var heightCount float64
// Skip heights if there's not enough validators to fill in a min sized committee.
if validatorCount < params.EpochLength*params.MinCommiteeSize {
heightCount = math.Floor(float64(validatorCount) / params.MinCommiteeSize)
for i := 0; i < int(heightCount); i++ {
heights = append(heights, (i*params.Cofactor)%params.EpochLength)
}
// Enough validators, fill in all the heights.
} else {
heightCount = params.EpochLength
for i := 0; i < int(heightCount); i++ {
heights = append(heights, i)
}
}
filled := 0
appendHeight := false
for i := 0; i < params.EpochLength-1; i++ {
appendHeight = false
for _, height := range heights {
if i == height {
appendHeight = true
}
}
if appendHeight {
filled++
heightCutoff = append(heightCutoff, filled*validatorCount/int(heightCount))
} else {
heightCutoff = append(heightCutoff, heightCutoff[len(heightCutoff)-1])
}
}
heightCutoff = append(heightCutoff, validatorCount)
// TODO: For the validators assigned to each height, split them up into
// committees for different shards. Do not assign the last END_EPOCH_GRACE_PERIOD
// heights in a epoch to any shards.
return heightCutoff
}

View File

@@ -1,6 +1,7 @@
package utils
import (
"math"
"reflect"
"testing"
@@ -31,3 +32,60 @@ func TestShuffleIndices(t *testing.T) {
t.Errorf("2 shuffled lists shouldn't be equal")
}
}
func TestCutOffValidatorSet(t *testing.T) {
// Test scenario #1: Assume there's enough validators to fill in all the heights.
validatorCount := params.EpochLength * params.MinCommiteeSize
cutoffsValidators := GetCutoffs(validatorCount)
// The length of cutoff list should be 65. Since there is 64 heights per epoch,
// it means during every height, a new set of 128 validators will form a committee.
expectedCount := int(math.Ceil(float64(validatorCount)/params.MinCommiteeSize)) + 1
if len(cutoffsValidators) != expectedCount {
t.Errorf("Incorrect count for cutoffs validator. Wanted: %v, Got: %v", expectedCount, len(cutoffsValidators))
}
// Verify each cutoff is an increment of MinCommiteeSize, it means 128 validators forms a
// a committee and get to attest per height.
count := 0
for _, cutoff := range cutoffsValidators {
if cutoff != count {
t.Errorf("cutoffsValidators did not get 128 increment. Wanted: count, Got: %v", cutoff)
}
count += params.MinCommiteeSize
}
// Test scenario #2: Assume there's not enough validators to fill in all the heights.
validatorCount = 1000
cutoffsValidators = unique(GetCutoffs(validatorCount))
// With 1000 validators, we can't attest every height. Given min committee size is 128,
// we can only attest 7 heights. round down 1000 / 128 equals to 7, means the length is 8.
expectedCount = int(math.Ceil(float64(validatorCount) / params.MinCommiteeSize))
if len(unique(cutoffsValidators)) != expectedCount {
t.Errorf("Incorrect count for cutoffs validator. Wanted: %v, Got: %v", expectedCount, validatorCount/params.MinCommiteeSize)
}
// Verify each cutoff is an increment of 142~143 (1000 / 7).
count = 0
for _, cutoff := range cutoffsValidators {
num := count * validatorCount / (len(cutoffsValidators) - 1)
if cutoff != num {
t.Errorf("cutoffsValidators did not get correct increment. Wanted: %v, Got: %v", num, cutoff)
}
count++
}
}
// helper function to remove duplicates in a int slice.
func unique(ints []int) []int {
keys := make(map[int]bool)
list := []int{}
for _, int := range ints {
if _, value := keys[int]; !value {
keys[int] = true
list = append(list, int)
}
}
return list
}