Add raw stake and median to super committee (#2880)

* [rpc][votepower] Add hack

* [consensus] Use hack, change from one addr to bls key

* update super committee rpc to add rawstake and median to output

* only retrieve total delegation once

* better name

* nil pointer check

Co-authored-by: Ganesha Upadhyaya <ganeshrvce@gmail.com>
pull/2884/head
Edgar Aroutiounian 5 years ago committed by GitHub
parent 451d16c14d
commit d4b8c11a8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      consensus/quorum/one-node-staked-vote.go
  2. 3
      consensus/quorum/quorum.go
  3. 5
      consensus/votepower/roster.go
  4. 43
      hmy/api_backend.go
  5. 20
      internal/hmyapi/common/hacks.go

@ -162,6 +162,13 @@ func (v *stakedVoteWeight) String() string {
return string(s)
}
// HACK later remove - unify votepower in UI (aka MarshalJSON)
func (v *stakedVoteWeight) SetRawStake(key shard.BLSPublicKey, d numeric.Dec) {
if voter, ok := v.roster.Voters[key]; ok {
voter.RawStake = d
}
}
// TODO remove this large method, use roster's own Marshal, mix it
// specific logic here
func (v *stakedVoteWeight) MarshalJSON() ([]byte, error) {
@ -173,6 +180,7 @@ func (v *stakedVoteWeight) MarshalJSON() ([]byte, error) {
RawPercent string `json:"voting-power-unnormalized"`
VotingPower string `json:"voting-power-%"`
EffectiveStake string `json:"effective-stake,omitempty"`
RawStake string `json:"raw-stake,omitempty"`
}
type t struct {
@ -196,10 +204,12 @@ func (v *stakedVoteWeight) MarshalJSON() ([]byte, error) {
voter.GroupPercent.String(),
voter.OverallPercent.String(),
"",
"",
}
if !voter.IsHarmonyNode {
externalCount++
member.EffectiveStake = voter.EffectiveStake.String()
member.RawStake = voter.RawStake.String()
}
parts[i] = member
i++

@ -127,11 +127,12 @@ type Decider interface {
type Registry struct {
Deciders map[string]Decider `json:"quorum-deciders"`
ExternalCount int `json:"external-slot-count"`
MedianStake numeric.Dec `json:"epos-median-stake"`
}
// NewRegistry ..
func NewRegistry(extern int) Registry {
return Registry{map[string]Decider{}, extern}
return Registry{map[string]Decider{}, extern, numeric.ZeroDec()}
}
// Transition ..

@ -6,11 +6,10 @@ import (
"math/big"
"sort"
"github.com/harmony-one/harmony/internal/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls"
common2 "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
"github.com/pkg/errors"
@ -72,6 +71,7 @@ type PureStakedVote struct {
Identity shard.BLSPublicKey `json:"bls-public-key"`
GroupPercent numeric.Dec `json:"group-percent"`
EffectiveStake numeric.Dec `json:"effective-stake"`
RawStake numeric.Dec `json:"raw-stake"`
}
// AccommodateHarmonyVote ..
@ -187,6 +187,7 @@ func Compute(subComm *shard.Committee, epoch *big.Int) (*Roster, error) {
Identity: staked[i].BLSPublicKey,
GroupPercent: numeric.ZeroDec(),
EffectiveStake: numeric.ZeroDec(),
RawStake: numeric.ZeroDec(),
},
OverallPercent: numeric.ZeroDec(),
IsHarmonyNode: false,

@ -561,6 +561,40 @@ func (b *APIBackend) GetCurrentUtilityMetrics() (*network.UtilityMetric, error)
return network.NewUtilityMetricSnapshot(b.hmy.BlockChain())
}
func (b *APIBackend) readAndUpdateRawStakes(
epoch *big.Int,
decider quorum.Decider,
comm shard.Committee,
rawStakes []effective.SlotPurchase,
validatorSpreads map[common.Address]numeric.Dec,
) {
for i := range comm.Slots {
slot := comm.Slots[i]
slotAddr := slot.EcdsaAddress
slotKey := slot.BLSPublicKey
spread, ok := validatorSpreads[slotAddr]
if !ok {
snapshot, err := b.hmy.BlockChain().ReadValidatorSnapshotAtEpoch(epoch, slotAddr)
if err != nil {
continue
}
wrapper := snapshot.Validator
spread = numeric.NewDecFromBigInt(wrapper.TotalDelegation()).
QuoInt64(int64(len(wrapper.SlotPubKeys)))
validatorSpreads[slotAddr] = spread
}
commonRPC.SetRawStake(decider, slotKey, spread)
// add entry to array for median calculation
rawStakes = append(rawStakes, effective.SlotPurchase{
slotAddr,
slotKey,
spread,
spread,
})
}
}
// GetSuperCommittees ..
func (b *APIBackend) GetSuperCommittees() (*quorum.Transition, error) {
nowE := b.hmy.BlockChain().CurrentHeader().Epoch()
@ -587,21 +621,30 @@ func (b *APIBackend) GetSuperCommittees() (*quorum.Transition, error) {
quorum.NewRegistry(stakedSlotsThen),
quorum.NewRegistry(stakedSlotsNow)
rawStakes := []effective.SlotPurchase{}
validatorSpreads := map[common.Address]numeric.Dec{}
for _, comm := range prevCommittee.Shards {
decider := quorum.NewDecider(quorum.SuperMajorityStake, comm.ShardID)
if _, err := decider.SetVoters(&comm, prevCommittee.Epoch); err != nil {
return nil, err
}
b.readAndUpdateRawStakes(thenE, decider, comm, rawStakes, validatorSpreads)
then.Deciders[fmt.Sprintf("shard-%d", comm.ShardID)] = decider
}
then.MedianStake = effective.Median(rawStakes)
rawStakes = []effective.SlotPurchase{}
validatorSpreads = map[common.Address]numeric.Dec{}
for _, comm := range nowCommittee.Shards {
decider := quorum.NewDecider(quorum.SuperMajorityStake, comm.ShardID)
if _, err := decider.SetVoters(&comm, nowCommittee.Epoch); err != nil {
return nil, err
}
b.readAndUpdateRawStakes(nowE, decider, comm, rawStakes, validatorSpreads)
now.Deciders[fmt.Sprintf("shard-%d", comm.ShardID)] = decider
}
then.MedianStake = effective.Median(rawStakes)
return &quorum.Transition{then, now}, nil
}

@ -0,0 +1,20 @@
package common
import (
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
)
type setRawStakeHack interface {
SetRawStake(key shard.BLSPublicKey, d numeric.Dec)
}
// SetRawStake is a hack, return value is if was successful or not at setting
func SetRawStake(q quorum.Decider, key shard.BLSPublicKey, d numeric.Dec) bool {
if setter, ok := q.(setRawStakeHack); ok {
setter.SetRawStake(key, d)
return true
}
return false
}
Loading…
Cancel
Save