2018-08-08 03:10:21 -07:00
|
|
|
# Transactions
|
|
|
|
|
|
|
|
## TxWithdrawDelegation
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
When a delegator wishes to withdraw their rewards it must send
|
2018-08-08 03:10:21 -07:00
|
|
|
`TxWithdrawDelegation`. Note that parts of this transaction logic are also
|
|
|
|
triggered each with any change in individual delegations, such as an unbond,
|
|
|
|
redelegation, or delegation of additional tokens to a specific validator.
|
|
|
|
|
|
|
|
```golang
|
|
|
|
type TxWithdrawDelegation struct {
|
|
|
|
delegatorAddr sdk.AccAddress
|
|
|
|
withdrawAddr sdk.AccAddress // address to make the withdrawal to
|
|
|
|
}
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
func WithdrawFromDelegator(delegatorAddr, withdrawAddr sdk.AccAddress)
|
|
|
|
height = GetHeight()
|
|
|
|
withdraw = GetDelegatorAllWithdraws(delegatorAddr, height)
|
2018-08-08 03:10:21 -07:00
|
|
|
AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal())
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoins
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
// get all distribution scenarios
|
2018-08-08 03:10:21 -07:00
|
|
|
delegations = GetDelegations(delegatorAddr)
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
// collect all entitled rewards
|
|
|
|
withdraw = 0
|
|
|
|
pool = stake.GetPool()
|
|
|
|
global = GetGlobal()
|
2018-08-08 03:10:21 -07:00
|
|
|
for delegation = range delegations
|
2018-08-15 20:33:26 -07:00
|
|
|
delDistr = GetDelegationDistribution(delegation.DelegatorAddr,
|
2018-08-08 03:10:21 -07:00
|
|
|
delegation.ValidatorAddr)
|
2018-08-15 20:33:26 -07:00
|
|
|
valDistr = GetValidatorDistribution(delegation.ValidatorAddr)
|
2018-08-08 03:10:21 -07:00
|
|
|
validator = GetValidator(delegation.ValidatorAddr)
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
global, ddWithdraw = delDistr.WithdrawRewards(global, valDistr, height, pool.BondedTokens,
|
|
|
|
validator.Tokens, validator.DelegatorShares, validator.Commission)
|
|
|
|
withdraw += ddWithdraw
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
SetGlobal(global)
|
|
|
|
return withdraw
|
2018-08-08 03:10:21 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
## TxWithdrawValidator
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
When a validator wishes to withdraw their rewards it must send
|
2018-08-08 03:10:21 -07:00
|
|
|
`TxWithdrawDelegation`. Note that parts of this transaction logic is also
|
|
|
|
triggered each with any change in individual delegations, such as an unbond,
|
|
|
|
redelegation, or delegation of additional tokens to a specific validator. This
|
2018-08-15 20:33:26 -07:00
|
|
|
transaction withdraws the validators commission fee, as well as any rewards
|
2018-08-08 03:10:21 -07:00
|
|
|
earning on their self-delegation.
|
|
|
|
|
2018-08-08 21:34:19 -07:00
|
|
|
```
|
2018-08-08 03:10:21 -07:00
|
|
|
type TxWithdrawValidator struct {
|
2018-08-15 20:33:26 -07:00
|
|
|
operatorAddr sdk.AccAddress // validator address to withdraw from
|
2018-08-08 03:10:21 -07:00
|
|
|
withdrawAddr sdk.AccAddress // address to make the withdrawal to
|
|
|
|
}
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
func WithdrawFromValidator(operatorAddr, withdrawAddr sdk.AccAddress)
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
height = GetHeight()
|
2018-08-08 03:10:21 -07:00
|
|
|
global = GetGlobal()
|
|
|
|
pool = GetPool()
|
|
|
|
ValDistr = GetValidatorDistribution(delegation.ValidatorAddr)
|
|
|
|
validator = GetValidator(delegation.ValidatorAddr)
|
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
// withdraw self-delegation
|
|
|
|
withdraw = GetDelegatorAllWithdraws(validator.OperatorAddr, height)
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
// withdrawal validator commission rewards
|
|
|
|
global, commission = valDistr.WithdrawCommission(global, valDistr, height, pool.BondedTokens,
|
|
|
|
validator.Tokens, validator.DelegatorShares, validator.Commission)
|
|
|
|
withdraw += commission
|
|
|
|
SetGlobal(global)
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal())
|
2018-08-08 03:10:21 -07:00
|
|
|
```
|
2018-08-15 20:33:26 -07:00
|
|
|
|
2018-08-14 20:33:40 -07:00
|
|
|
## Common calculations
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-08 21:34:19 -07:00
|
|
|
### Update total validator accum
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-08 21:34:19 -07:00
|
|
|
The total amount of validator accum must be calculated in order to determine
|
2018-08-14 10:45:13 -07:00
|
|
|
the amount of pool tokens which a validator is entitled to at a particular
|
|
|
|
block. The accum is always additive to the existing accum. This term is to be
|
2018-08-14 20:33:40 -07:00
|
|
|
updates each time rewards are withdrawn from the system.
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-08 21:34:19 -07:00
|
|
|
```
|
2018-08-14 10:45:13 -07:00
|
|
|
func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec)
|
|
|
|
blocks = height - g.TotalValAccumUpdateHeight
|
|
|
|
g.TotalValAccum += totalDelShares * blocks
|
2018-08-15 17:03:39 -07:00
|
|
|
g.TotalValAccumUpdateHeight = height
|
2018-08-14 10:45:13 -07:00
|
|
|
```
|
|
|
|
|
2018-08-14 20:33:40 -07:00
|
|
|
### Update validator's accums
|
2018-08-08 21:34:19 -07:00
|
|
|
|
2018-08-14 10:45:13 -07:00
|
|
|
The total amount of delegator accum must be updated in order to determine the
|
|
|
|
amount of pool tokens which each delegator is entitled to, relative to the
|
|
|
|
other delegators for that validator. The accum is always additive to
|
|
|
|
the existing accum. This term is to be updated each time a
|
|
|
|
withdrawal is made from a validator.
|
2018-08-08 21:34:19 -07:00
|
|
|
|
2018-08-14 10:45:13 -07:00
|
|
|
```
|
|
|
|
func (vd ValidatorDistribution) UpdateTotalDelAccum(height int64, totalDelShares Dec)
|
|
|
|
blocks = height - vd.TotalDelAccumUpdateHeight
|
|
|
|
vd.TotalDelAccum += totalDelShares * blocks
|
2018-08-15 17:03:39 -07:00
|
|
|
vd.TotalDelAccumUpdateHeight = height
|
2018-08-08 21:34:19 -07:00
|
|
|
```
|
|
|
|
|
2018-08-14 20:33:40 -07:00
|
|
|
### Global pool to validator pool
|
2018-08-08 21:34:19 -07:00
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
Every time a validator or delegator make a withdraw or the validator is the
|
|
|
|
proposer and receives new tokens - the relevant validator must move tokens from
|
|
|
|
the passive global pool to their own pool.
|
2018-08-08 21:34:19 -07:00
|
|
|
|
|
|
|
```
|
2018-08-14 20:33:40 -07:00
|
|
|
func (vd ValidatorDistribution) TakeAccum(g Global, height int64, totalBonded, vdTokens Dec) g Global
|
2018-08-14 10:45:13 -07:00
|
|
|
g.UpdateTotalValAccum(height, totalBondedShares)
|
2018-08-14 20:33:40 -07:00
|
|
|
g.UpdateValAccum(height, totalBondedShares)
|
|
|
|
|
|
|
|
// update the validators pool
|
|
|
|
blocks = height - vd.GlobalWithdrawalHeight
|
2018-08-15 17:03:39 -07:00
|
|
|
vd.GlobalWithdrawalHeight = height
|
2018-08-14 20:33:40 -07:00
|
|
|
accum = blocks * vdTokens
|
|
|
|
withdrawalTokens := g.Pool * accum / g.TotalValAccum
|
|
|
|
|
2018-08-15 01:12:44 -07:00
|
|
|
g.TotalValAccum -= accumm
|
2018-08-14 20:33:40 -07:00
|
|
|
vd.Pool += withdrawalTokens
|
|
|
|
g.Pool -= withdrawalTokens
|
|
|
|
|
|
|
|
return g
|
2018-08-08 21:34:19 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
|
2018-08-14 20:33:40 -07:00
|
|
|
### Delegation's withdrawal
|
2018-08-08 03:10:21 -07:00
|
|
|
|
2018-08-15 20:33:26 -07:00
|
|
|
For delegations (including validator's self-delegation) all rewards from reward pool
|
|
|
|
are subject to commission rate from the operator of the validator.
|
2018-08-08 21:34:19 -07:00
|
|
|
|
2018-08-08 03:10:21 -07:00
|
|
|
```
|
2018-08-15 17:03:39 -07:00
|
|
|
func (dd DelegatorDist) WithdrawRewards(g Global, vd ValidatorDistribution,
|
2018-08-15 20:33:26 -07:00
|
|
|
height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins)
|
2018-08-14 20:33:40 -07:00
|
|
|
|
2018-08-15 01:12:44 -07:00
|
|
|
vd.UpdateTotalDelAccum(height, totalDelShares)
|
|
|
|
g = vd.TakeAccum(g, height, totalBonded, vdTokens)
|
2018-08-14 20:33:40 -07:00
|
|
|
|
2018-08-15 01:12:44 -07:00
|
|
|
blocks = height - dd.WithdrawalHeight
|
2018-08-15 17:03:39 -07:00
|
|
|
dd.WithdrawalHeight = height
|
2018-08-15 01:12:44 -07:00
|
|
|
accum = delegatorShares * blocks * (1 - commissionRate)
|
|
|
|
|
2018-08-15 17:03:39 -07:00
|
|
|
withdrawalTokens := vd.Pool * accum / vd.TotalDelAccum
|
|
|
|
vd.TotalDelAccum -= accum
|
|
|
|
|
2018-08-15 01:12:44 -07:00
|
|
|
vd.Pool -= withdrawalTokens
|
|
|
|
vd.TotalDelAccum -= accum
|
2018-08-15 17:03:39 -07:00
|
|
|
return g, withdrawalTokens
|
2018-08-14 20:33:40 -07:00
|
|
|
|
2018-08-08 03:10:21 -07:00
|
|
|
```
|
|
|
|
|
2018-08-14 20:33:40 -07:00
|
|
|
### Validators's commission withdrawal
|
2018-08-08 03:10:21 -07:00
|
|
|
|
|
|
|
Similar to a delegator's entitlement, but with recipient shares based on the
|
|
|
|
commission portion of bonded tokens.
|
|
|
|
|
|
|
|
```
|
2018-08-15 17:03:39 -07:00
|
|
|
func (vd ValidatorDist) WithdrawCommission(g Global, vd ValidatorDistribution,
|
2018-08-15 20:33:26 -07:00
|
|
|
height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins)
|
2018-08-15 01:12:44 -07:00
|
|
|
|
|
|
|
vd.UpdateTotalDelAccum(height, totalDelShares)
|
|
|
|
g = vd.TakeAccum(g, height, totalBonded, vdTokens)
|
|
|
|
|
|
|
|
blocks = height - vd.CommissionWithdrawalHeight
|
2018-08-15 17:03:39 -07:00
|
|
|
vd.CommissionWithdrawalHeight = height
|
2018-08-15 01:12:44 -07:00
|
|
|
accum = delegatorShares * blocks * (commissionRate)
|
|
|
|
|
2018-08-15 17:03:39 -07:00
|
|
|
withdrawalTokens := vd.Pool * accum / vd.TotalDelAccum
|
|
|
|
vd.TotalDelAccum -= accum
|
2018-08-15 01:12:44 -07:00
|
|
|
|
|
|
|
vd.Pool -= withdrawalTokens
|
|
|
|
vd.TotalDelAccum -= accum
|
|
|
|
|
2018-08-15 17:03:39 -07:00
|
|
|
return g, withdrawalTokens
|
2018-08-08 03:10:21 -07:00
|
|
|
```
|