mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-27 13:58:05 +00:00
ec17654986
add dao which takes care about all CRUD operations on storage remove blockchain state since everything is stored on change remove storage operations from structs(entities) move structs to entities package
99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
package entities
|
|
|
|
import (
|
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
|
"github.com/CityOfZion/neo-go/pkg/io"
|
|
"github.com/CityOfZion/neo-go/pkg/util"
|
|
)
|
|
|
|
// ValidatorState holds the state of a validator.
|
|
type ValidatorState struct {
|
|
PublicKey *keys.PublicKey
|
|
Registered bool
|
|
Votes util.Fixed8
|
|
}
|
|
|
|
// RegisteredAndHasVotes returns true or false whether Validator is registered and has votes.
|
|
func (vs *ValidatorState) RegisteredAndHasVotes() bool {
|
|
return vs.Registered && vs.Votes > util.Fixed8(0)
|
|
}
|
|
|
|
// EncodeBinary encodes ValidatorState to the given BinWriter.
|
|
func (vs *ValidatorState) EncodeBinary(bw *io.BinWriter) {
|
|
vs.PublicKey.EncodeBinary(bw)
|
|
bw.WriteLE(vs.Registered)
|
|
bw.WriteLE(vs.Votes)
|
|
}
|
|
|
|
// DecodeBinary decodes ValidatorState from the given BinReader.
|
|
func (vs *ValidatorState) DecodeBinary(reader *io.BinReader) {
|
|
vs.PublicKey = &keys.PublicKey{}
|
|
vs.PublicKey.DecodeBinary(reader)
|
|
reader.ReadLE(&vs.Registered)
|
|
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
|
|
}
|