core: add weighted function for validators
This commit is contained in:
parent
672f314be0
commit
419b031e96
2 changed files with 67 additions and 17 deletions
|
@ -1289,23 +1289,8 @@ func (bc *Blockchain) GetValidators(txes... *transaction.Transaction) ([]*keys.P
|
||||||
}
|
}
|
||||||
|
|
||||||
validators := getValidatorsFromStore(chainState.store)
|
validators := getValidatorsFromStore(chainState.store)
|
||||||
for _, validator := range validators {
|
|
||||||
if validator.Votes > util.Fixed8(0) {
|
count := GetValidatorsWeightedAverage(validators)
|
||||||
// Select count of votes with strange logic:
|
|
||||||
// int count = (int)snapshot.ValidatorsCount.Get().Votes.Select((p, i) => new
|
|
||||||
// {
|
|
||||||
// Count = i,
|
|
||||||
// Votes = p
|
|
||||||
// }).Where(p => p.Votes > Fixed8.Zero).ToArray().WeightedFilter(0.25, 0.75, p => p.Votes.GetData(), (p, w) => new
|
|
||||||
// {
|
|
||||||
// p.Count,
|
|
||||||
// Weight = w
|
|
||||||
// }).WeightedAverage(p => p.Count, p => p.Weight);
|
|
||||||
// count = Math.Max(count, Blockchain.StandbyValidators.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var count int
|
|
||||||
count = 0
|
|
||||||
standByValidators, err := bc.GetStandByValidators()
|
standByValidators, err := bc.GetStandByValidators()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -107,3 +107,68 @@ func (vs *ValidatorState) DecodeBinary(reader *io.BinReader) {
|
||||||
reader.ReadLE(&vs.Registered)
|
reader.ReadLE(&vs.Registered)
|
||||||
reader.ReadLE(&vs.Votes)
|
reader.ReadLE(&vs.Votes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValidatorsWeightedAverage applies weighted filter based on votes for validator and returns number of validators.
|
||||||
|
// Get back to it with further investigation in https://github.com/nspcc-dev/neo-go/issues/512.
|
||||||
|
func GetValidatorsWeightedAverage(validators []*ValidatorState) int {
|
||||||
|
return int(weightedAverage(applyWeightedFilter(validators)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyWeightedFilter is an implementation of the filter for validators votes.
|
||||||
|
// C# reference https://github.com/neo-project/neo/blob/41caff115c28d6c7665b2a7ac72967e7ce82e921/neo/Helper.cs#L273
|
||||||
|
func applyWeightedFilter(validators []*ValidatorState) map[*ValidatorState]float64 {
|
||||||
|
var validatorsWithVotes []*ValidatorState
|
||||||
|
var amount float64
|
||||||
|
|
||||||
|
weightedVotes := make(map[*ValidatorState]float64)
|
||||||
|
start := 0.25
|
||||||
|
end := 0.75
|
||||||
|
sum := float64(0)
|
||||||
|
current := float64(0)
|
||||||
|
|
||||||
|
for _, validator := range validators {
|
||||||
|
if validator.Votes > util.Fixed8(0) {
|
||||||
|
validatorsWithVotes = append(validatorsWithVotes, validator)
|
||||||
|
amount += validator.Votes.FloatValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, validator := range validatorsWithVotes {
|
||||||
|
if current >= end {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
weight := validator.Votes.FloatValue()
|
||||||
|
sum += weight
|
||||||
|
old := current
|
||||||
|
current = sum / amount
|
||||||
|
|
||||||
|
if current <= start {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if old < start {
|
||||||
|
if current > end {
|
||||||
|
weight = (end - start) * amount
|
||||||
|
} else {
|
||||||
|
weight = (current - start) * amount
|
||||||
|
}
|
||||||
|
} else if current > end {
|
||||||
|
weight = (end - old) * amount
|
||||||
|
}
|
||||||
|
weightedVotes[validator] = weight
|
||||||
|
}
|
||||||
|
return weightedVotes
|
||||||
|
}
|
||||||
|
|
||||||
|
func weightedAverage(weightedVotes map[*ValidatorState]float64) float64 {
|
||||||
|
sumWeight := float64(0)
|
||||||
|
sumValue := float64(0)
|
||||||
|
for vState, weight := range weightedVotes {
|
||||||
|
sumWeight += weight
|
||||||
|
sumValue += vState.Votes.FloatValue() * weight
|
||||||
|
}
|
||||||
|
if sumValue == 0 || sumWeight == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return sumValue / sumWeight
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue