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

169 lines
4.7 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"
)
var (
// BlockReward is the block reward, to be split evenly among block signers in pre-staking era.
BlockReward = new(big.Int).Mul(big.NewInt(24), big.NewInt(denominations.One))
// BaseStakedReward is the flat-rate block reward for epos staking launch.
// 28 ONE per block
BaseStakedReward = numeric.NewDecFromBigInt(new(big.Int).Mul(
big.NewInt(28), big.NewInt(denominations.One),
))
// FiveSecondsBaseStakedReward is the flat-rate block reward after epoch 230.
// 17.5 ONE per block
FiveSecondsBaseStakedReward = numeric.NewDecFromBigInt(new(big.Int).Mul(
big.NewInt(17.5*denominations.Nano), big.NewInt(denominations.Nano),
))
// TwoSecondsBaseStakedReward is the flat-rate block reward after epoch 360.
// 7 ONE per block
TwoSecondsBaseStakedReward = numeric.NewDecFromBigInt(new(big.Int).Mul(
big.NewInt(7*denominations.Nano), big.NewInt(denominations.Nano),
))
// BlockRewardStakedCase is the baseline block reward in staked case -
totalTokens = numeric.NewDecFromBigInt(
new(big.Int).Mul(big.NewInt(12600000000), big.NewInt(denominations.One)),
)
targetStakedPercentage = numeric.MustNewDecFromStr("0.35")
dynamicAdjust = numeric.MustNewDecFromStr("0.4")
// ErrPayoutNotEqualBlockReward ..
ErrPayoutNotEqualBlockReward = errors.New(
"total payout not equal to blockreward",
)
// NoReward ..
NoReward = big.NewInt(0)
// EmptyPayout ..
EmptyPayout = noReward{}
)
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.NewDecFromBigInt(soFarDoledOut)
for _, electedValAdr := range active.StakedValidators().Addrs {
wrapper, err := beaconchain.ReadValidatorInformation(electedValAdr)
if err != nil {
return nil, nil, err
}
stakedNow = stakedNow.Add(
numeric.NewDecFromBigInt(wrapper.TotalDelegation()),
)
}
percentage := stakedNow.Quo(totalTokens.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
}