Add low-level validator/delegator block reward logic

pull/1830/head
Rongjian Lan 5 years ago
parent b013e1fea3
commit 740aeac3e7
  1. 38
      core/state/statedb.go
  2. 2
      core/vm/interface.go
  3. 12
      numeric/decimal.go
  4. 1
      staking/types/delegation.go
  5. 10
      staking/types/validator.go

@ -23,6 +23,8 @@ import (
"math/big" "math/big"
"sort" "sort"
"github.com/harmony-one/harmony/numeric"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -727,9 +729,39 @@ func (db *DB) IsValidator(addr common.Address) bool {
return so.IsValidator(db.db) return so.IsValidator(db.db)
} }
func (db *DB) AddReward(validator common.Address, reward *big.Int) { // AddReward distributes the reward to all the delegators based on stake percentage.
//TODO: implement reward logic func (db *DB) AddReward(validator common.Address, reward *big.Int) error {
// the reward will be distributed to all the delegators based on stake percentage. rewardPool := big.NewInt(0).Set(reward)
wrapper := db.GetStakingInfo(validator)
if wrapper == nil {
return errors.New("failed to distribute rewards: validator does not exist")
}
// Payout commission
commissionInt := wrapper.Validator.CommissionRates.Rate.MulInt(reward).RoundInt()
wrapper.Delegations[0].Reward.Add(wrapper.Delegations[0].Reward, commissionInt)
rewardPool.Sub(rewardPool, commissionInt)
totalRewardForDelegators := big.NewInt(0).Set(rewardPool)
// Payout each delegator's reward pro-rata
totalDelegationDec := numeric.NewDecFromBigInt(wrapper.TotalDelegation())
for i := range wrapper.Delegations {
delegation := wrapper.Delegations[i]
percentage := numeric.NewDecFromBigInt(delegation.Amount).Quo(totalDelegationDec) // percentage = <this_delegator_amount>/<total_delegation>
rewardInt := percentage.MulInt(totalRewardForDelegators).RoundInt()
delegation.Reward.Add(delegation.Reward, rewardInt)
rewardPool.Sub(rewardPool, rewardInt)
}
// The last remaining bit belongs to the validator (remember the validator's self delegation is always at index 0)
if rewardPool.Cmp(big.NewInt(0)) > 0 {
wrapper.Delegations[0].Reward.Add(wrapper.Delegations[0].Reward, rewardPool)
}
return db.UpdateStakingInfo(validator, wrapper)
} }
func (db *DB) CollectReward(delegator common.Address) { func (db *DB) CollectReward(delegator common.Address) {

@ -45,7 +45,7 @@ type StateDB interface {
SetValidatorFlag(common.Address) SetValidatorFlag(common.Address)
UnsetValidatorFlag(common.Address) UnsetValidatorFlag(common.Address)
IsValidator(common.Address) bool IsValidator(common.Address) bool
AddReward(common.Address, *big.Int) AddReward(common.Address, *big.Int) error
CollectReward(common.Address) CollectReward(common.Address)
AddRefund(uint64) AddRefund(uint64)

@ -483,9 +483,9 @@ func (d Dec) RoundInt64() int64 {
} }
// RoundInt round the decimal using bankers rounding // RoundInt round the decimal using bankers rounding
//func (d Dec) RoundInt() big.Int { func (d Dec) RoundInt() *big.Int {
// return NewIntFromBigInt(chopPrecisionAndRoundNonMutative(d.Int)) return chopPrecisionAndRoundNonMutative(d.Int)
//} }
//___________________________________________________________________________________ //___________________________________________________________________________________
@ -509,9 +509,9 @@ func (d Dec) TruncateInt64() int64 {
} }
// TruncateInt truncates the decimals from the number and returns an Int // TruncateInt truncates the decimals from the number and returns an Int
//func (d Dec) TruncateInt() big.Int { func (d Dec) TruncateInt() *big.Int {
// return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.Int)) return chopPrecisionAndTruncateNonMutative(d.Int)
//} }
// TruncateDec truncates the decimals from the number and returns a Dec // TruncateDec truncates the decimals from the number and returns a Dec
func (d Dec) TruncateDec() Dec { func (d Dec) TruncateDec() Dec {

@ -18,6 +18,7 @@ var (
type Delegation struct { type Delegation struct {
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"`
Amount *big.Int `json:"amount" yaml:"amount"` Amount *big.Int `json:"amount" yaml:"amount"`
Reward *big.Int `json:"reward" yaml:"reward"`
Entries []*UndelegationEntry `json:"entries" yaml:"entries"` Entries []*UndelegationEntry `json:"entries" yaml:"entries"`
} }

@ -68,6 +68,15 @@ func printSlotPubKeys(pubKeys []shard.BlsPublicKey) string {
return str return str
} }
// TotalDelegation - return the total amount of token in delegation
func (w *ValidatorWrapper) TotalDelegation() *big.Int {
total := big.NewInt(0)
for _, entry := range w.Delegations {
total.Add(total, entry.Amount)
}
return total
}
// Description - some possible IRL connections // Description - some possible IRL connections
type Description struct { type Description struct {
Name string `json:"name" yaml:"name"` // name Name string `json:"name" yaml:"name"` // name
@ -157,6 +166,7 @@ func CreateValidatorFromNewMsg(val *CreateValidator) (*Validator, error) {
commission := Commission{val.CommissionRates, new(big.Int)} commission := Commission{val.CommissionRates, new(big.Int)}
pubKeys := []shard.BlsPublicKey{} pubKeys := []shard.BlsPublicKey{}
pubKeys = append(pubKeys, val.SlotPubKeys...) pubKeys = append(pubKeys, val.SlotPubKeys...)
// TODO: a new validator should have a minimum of 1 token as self delegation, and that should be added as a delegation entry here.
v := Validator{val.ValidatorAddress, pubKeys, v := Validator{val.ValidatorAddress, pubKeys,
val.Amount, new(big.Int), val.MinSelfDelegation, val.MaxTotalDelegation, false, val.Amount, new(big.Int), val.MinSelfDelegation, val.MaxTotalDelegation, false,
commission, desc, big.NewInt(0)} commission, desc, big.NewInt(0)}

Loading…
Cancel
Save