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/staking/network/reward.go

148 lines
3.8 KiB

package network
import (
"errors"
"math/big"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/consensus/reward"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/numeric"
"github.com/harmony-one/harmony/shard"
stakingReward "github.com/harmony-one/harmony/staking/reward"
)
var (
// ErrPayoutNotEqualBlockReward ..
ErrPayoutNotEqualBlockReward = errors.New(
"total payout not equal to blockreward",
)
// EmptyPayout ..
EmptyPayout = noReward{}
targetStakedPercentage = numeric.MustNewDecFromStr("0.35")
dynamicAdjust = numeric.MustNewDecFromStr("0.4")
)
type ignoreMissing struct{}
func (ignoreMissing) MissingSigners() shard.SlotList {
return shard.SlotList{}
}
type noReward struct{ ignoreMissing }
func (noReward) ReadRoundResult() *reward.CompletedRound {
return &reward.CompletedRound{
Total: big.NewInt(0),
BeaconchainAward: []reward.Payout{},
ShardChainAward: []reward.Payout{},
}
}
type preStakingEra struct {
ignoreMissing
payout *big.Int
}
// NewPreStakingEraRewarded ..
func NewPreStakingEraRewarded(totalAmount *big.Int) reward.Reader {
return &preStakingEra{ignoreMissing{}, totalAmount}
}
func (p *preStakingEra) ReadRoundResult() *reward.CompletedRound {
return &reward.CompletedRound{
Total: p.payout,
BeaconchainAward: []reward.Payout{},
ShardChainAward: []reward.Payout{},
}
}
type stakingEra struct {
reward.CompletedRound
missingSigners shard.SlotList
}
// NewStakingEraRewardForRound ..
func NewStakingEraRewardForRound(
totalPayout *big.Int,
mia shard.SlotList,
beaconP, shardP []reward.Payout,
) reward.Reader {
return &stakingEra{
CompletedRound: reward.CompletedRound{
Total: totalPayout,
BeaconchainAward: beaconP,
ShardChainAward: shardP,
},
missingSigners: mia,
}
}
// MissingSigners ..
func (r *stakingEra) MissingSigners() shard.SlotList {
return r.missingSigners
}
// ReadRoundResult ..
func (r *stakingEra) ReadRoundResult() *reward.CompletedRound {
return &r.CompletedRound
}
func adjust(amount numeric.Dec) numeric.Dec {
return amount.MulTruncate(
numeric.NewDecFromBigInt(big.NewInt(denominations.One)),
)
}
// Adjustment ..
func Adjustment(percentageStaked numeric.Dec) (numeric.Dec, numeric.Dec) {
howMuchOff := targetStakedPercentage.Sub(percentageStaked)
adjustBy := adjust(
howMuchOff.MulTruncate(numeric.NewDec(100)).Mul(dynamicAdjust),
)
return howMuchOff, adjustBy
}
// WhatPercentStakedNow ..
func WhatPercentStakedNow(
beaconchain engine.ChainReader,
timestamp int64,
) (*big.Int, *numeric.Dec, error) {
stakedNow := numeric.ZeroDec()
// Only elected validators' stake is counted in stake ratio because only their stake is under slashing risk
active, err := beaconchain.ReadShardState(beaconchain.CurrentBlock().Epoch())
if err != nil {
return nil, nil, err
}
soFarDoledOut, err := beaconchain.ReadBlockRewardAccumulator(
beaconchain.CurrentHeader().Number().Uint64(),
)
if err != nil {
return nil, nil, err
}
dole := numeric.NewDecFromBigIntWithPrec(soFarDoledOut, 18)
for _, electedValAdr := range active.StakedValidators().Addrs {
wrapper, err := beaconchain.ReadValidatorInformation(electedValAdr)
if err != nil {
return nil, nil, err
}
stakedNow = stakedNow.Add(
numeric.NewDecFromBigIntWithPrec(wrapper.TotalDelegation(), 18),
)
}
percentage := stakedNow.Quo(stakingReward.TotalInitialTokens.Mul(
reward.PercentageForTimeStamp(timestamp),
).Add(dole))
utils.Logger().Info().
Str("so-far-doled-out", dole.String()).
Str("staked-percentage", percentage.String()).
Str("currently-staked", stakedNow.String()).
Msg("Computed how much staked right now")
return soFarDoledOut, &percentage, nil
}