docs: x/distribution spec (#8928)

* EndBlock => BeginBlock

* Add high-level algorithm

* Update documentation on params invariant

* Comment fix

* Update and extend BeginBlock documentation

* Update hooks documentation

* New intro to the concepts

* Update messages documentation

* Write in full sentences

Co-authored-by: Robert Zaremba <robert@zaremba.ch>

* spelling error

* change link

* slashing spec clarification

* Revert "slashing spec clarification"

This reverts commit b08b5a8533ca9d355a0afb0e58254b95487ce880.

* Update x/distribution/spec/04_messages.md

Co-authored-by: Robert Zaremba <robert@zaremba.ch>

* Update x/distribution/spec/03_begin_block.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* update link to latest version

* Update x/distribution/spec/04_messages.md

Co-authored-by: Robert Zaremba <robert@zaremba.ch>

* clarify note on removed validator

* clarify validator removed hook

* clarify validator created hook

* clarify delegation modified/created hook

* clarify slash hook

* clarify possesive singular situation

* clarify hooks.go

* Move comment to clearer position

* Update x/distribution/spec/01_concepts.md

Co-authored-by: Barrie Byron <barrie.byron@tendermint.com>

* clarifications in concepts file

* Clarify introductory paragraphs

* communitytax => community_tax

* Apply suggestions from code review

Co-authored-by: Barrie Byron <barrie.byron@tendermint.com>
Co-authored-by: Robert Zaremba <robert@zaremba.ch>

* Update delegator rewards descirption

* Remove "this"

* Fix error in non-proposer validator rewards spec

* Clarify validator rewards high level description

* Update x/distribution/spec/04_messages.md

* Clarify what fees are

* Misc grammar and style fixes

* Apply suggestions from code review

Co-authored-by: Barrie Byron <barrie.byron@tendermint.com>

* Apply suggestions from code review

Co-authored-by: Barrie Byron <barrie.byron@tendermint.com>
Co-authored-by: Ethan Buchman <ethan@coinculture.info>

Co-authored-by: Jack Zampolin <jack.zampolin@gmail.com>
Co-authored-by: Marko <marbar3778@yahoo.com>
Co-authored-by: Robert Zaremba <robert@zaremba.ch>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Barrie Byron <barrie.byron@tendermint.com>
Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: Ethan Buchman <ethan@coinculture.info>
This commit is contained in:
Rikard Hjort 2021-05-03 20:40:34 +02:00 committed by GitHub
parent d19791be89
commit a3feeed665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 238 additions and 213 deletions

View File

@ -22,7 +22,7 @@ func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
h.k.initializeValidator(ctx, val)
}
// cleanup for after validator is removed
// AfterValidatorRemoved performs clean up after a validator is removed
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) {
// fetch outstanding
outstanding := h.k.GetValidatorOutstandingRewardsCoins(ctx, valAddr)
@ -52,7 +52,9 @@ func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr
}
}
// add outstanding to community pool
// Add outstanding to community pool
// The validator is removed only after it has no more delegations.
// This operation sends only the remaining dust to the community pool.
feePool := h.k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(outstanding...)
h.k.SetFeePool(ctx, feePool)

View File

@ -3,12 +3,21 @@ order: 1
-->
# Concepts
In Proof of Stake (PoS) blockchains, rewards gained from transaction fees are paid to validators. The fee distribution module fairly distributes the rewards to the validators' constituent delegators.
Rewards are calculated per period. The period is updated each time a validator's delegation changes, for example, when the validator receives a new delegation.
The rewards for a single validator can then be calculated by taking the total rewards for the period before the delegation started, minus the current total rewards.
To learn more, see the [F1 Fee Distribution paper](/docs/spec/fee_distribution/f1_fee_distr.pdf).
The commission to the validator is paid when the validator is removed or when the validator requests a withdrawal.
The commission is calculated and incremented at every `BeginBlock` operation to update accumulated fee amounts.
The rewards to a delegator are distributed when the delegation is changed or removed, or a withdrawal is requested.
Before rewards are distributed, all slashes to the validator that occurred during the current delegation are applied.
## Reference Counting in F1 Fee Distribution
In F1 fee distribution, in order to calculate the rewards a delegator ought to receive when they
withdraw their delegation, we must read the terms of the summation of rewards divided by tokens from
the period which they ended when they delegated, and the final period (created when they withdraw).
In F1 fee distribution, the rewards a delegator receives are calculated when their delegation is withdrawn. This calculation must read the terms of the summation of rewards divided by the share of tokens from the period which they ended when they delegated, and the final period that was created for the withdrawal.
Additionally, as slashes change the amount of tokens a delegation will have (but we calculate this lazily,
only when a delegator un-delegates), we must calculate rewards in separate periods before / after any slashes

View File

@ -36,7 +36,7 @@ Validator distribution information for the relevant validator is updated each ti
1. delegation amount to a validator is updated,
2. a validator successfully proposes a block and receives a reward,
3. any delegator withdraws from a validator, or
4. the validator withdraws it's commission.
4. the validator withdraws its commission.
- ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)`

View File

@ -0,0 +1,87 @@
<!--
order: 3
-->
# Begin Block
At each `BeginBlock`, all fees received in the previous block are transferred to
the distribution `ModuleAccount` account. When a delegator or validator
withdraws their rewards, they are taken out of the `ModuleAccount`. During begin
block, the different claims on the fees collected are updated as follows:
- The block proposer of the previous height and its delegators receive between 1% and 5% of fee rewards.
- The reserve community tax is charged.
- The remainder is distributed proportionally by voting power to all bonded validators
To incentivize validators to wait and include additional pre-commits in the block, the block proposer reward is calculated from Tendermint pre-commit messages.
## The Distribution Scheme
See [params](07_params.md) for description of parameters.
Let `fees` be the total fees collected in the previous block, including
inflationary rewards to the stake. All fees are collected in a specific module
account during the block. During `BeginBlock`, they are sent to the
`"distribution"` `ModuleAccount`. No other sending of tokens occurs. Instead, the
rewards each account is entitled to are stored, and withdrawals can be triggered
through the messages `FundCommunityPool`, `WithdrawValidatorCommission` and
`WithdrawDelegatorReward`.
### Reward to the Community Pool
The community pool gets `community_tax * fees`, plus any remaining dust after
validators get their rewards that are always rounded down to the nearest
integer value.
### Reward To the Validators
The proposer receives a base reward of `fees * baseproposerreward` and a bonus
of `fees * bonusproposerreward * P`, where `P = (total power of validators with
included precommits / total bonded validator power)`. The more precommits the
proposer includes, the larger `P` is. `P` can never be larger than `1.00` (since
only bonded validators can supply valid precommits) and is always larger than
`2/3`.
Any remaining fees are distributed among all the bonded validators, including
the proposer, in proportion to their consensus power.
```
powFrac = validator power / total bonded validator power
proposerMul = baseproposerreward + bonusproposerreward * P
voteMul = 1 - communitytax - proposerMul
```
In total, the proposer receives `fees * (voteMul * powFrac + proposerMul)`.
All other validators receive `fees * voteMul * powFrac`.
### Rewards to Delegators
Each validator's rewards are distributed to its delegators. The validator also
has a self-delegation that is treated like a regular delegation in
distribution calculations.
The validator sets a commission rate. The commission rate is flexible, but each
validator sets a maximum rate and a maximum daily increase. These maximums cannot be exceeded and protect delegators from sudden increases of validator commission rates to prevent validators from taking all of the rewards.
The outstanding rewards that the operator is entitled to are stored in
`ValidatorAccumulatedCommission`, while the rewards the delegators are entitled
to are stored in `ValidatorCurrentRewards`. The [F1 fee distribution
scheme](01_concepts.md) is used to calculate the rewards per delegator as they
withdraw or update their delegation, and is thus not handled in `BeginBlock`.
### Example Distribution
For this example distribution, the underlying consensus engine selects block proposers in
proportion to their power relative to the entire bonded power.
All validators are equally performant at including pre-commits in their proposed
blocks. Then hold `(precommits included) / (total bonded validator power)`
constant so that the amortized block reward for the validator is `( validator power / total bonded power) * (1 - community tax rate)` of
the total rewards. Consequently, the reward for a single delegator is:
```
(delegator proportion of the validator power / validator power) * (validator power / total bonded power)
* (1 - community tax rate) * (1 - validator commision rate)
= (delegator proportion of the validator power / total bonded power) * (1 -
community tax rate) * (1 - validator commision rate)
```

View File

@ -1,33 +0,0 @@
<!--
order: 3
-->
# End Block
At each `EndBlock`, the fees received are transferred to the distribution `ModuleAccount`, as it's the account the one who keeps track of the flow of coins in (as in this case) and out the module. The fees are also allocated to the proposer, community fund and global pool. When the validator is the proposer of the round, that validator (and their delegators) receives between 1% and 5% of fee rewards, the reserve community tax is then charged, then the remainder is distributed proportionally by voting power to all bonded validators independent of whether they voted (social distribution). Note the social distribution is applied to proposer validator in addition to the proposer reward.
The amount of proposer reward is calculated from pre-commits Tendermint messages in order to incentivize validators to wait and include additional pre-commits in the block. All provision rewards are added to a provision reward pool which validator holds individually (`ValidatorDistribution.ProvisionsRewardPool`).
```go
func AllocateTokens(feesCollected sdk.Coins, feePool FeePool, proposer ValidatorDistribution,
sumPowerPrecommitValidators, totalBondedTokens, communityTax,
proposerCommissionRate sdk.Dec)
SendCoins(FeeCollectorAddr, DistributionModuleAccAddr, feesCollected)
feesCollectedDec = MakeDecCoins(feesCollected)
proposerReward = feesCollectedDec * (0.01 + 0.04
* sumPowerPrecommitValidators / totalBondedTokens)
commission = proposerReward * proposerCommissionRate
proposer.PoolCommission += commission
proposer.Pool += proposerReward - commission
communityFunding = feesCollectedDec * communityTax
feePool.CommunityFund += communityFunding
poolReceived = feesCollectedDec - proposerReward - communityFunding
feePool.Pool += poolReceived
SetValidatorDistribution(proposer)
SetFeePool(feePool)
```

View File

@ -6,13 +6,16 @@ order: 4
## MsgSetWithdrawAddress
By default a withdrawal address is delegator address. If a delegator wants to change it's
withdrawal address it must send `MsgSetWithdrawAddress`.
By default, the withdraw address is the delegator address. To change its withdraw address, a delegator must send a `MsgSetWithdrawAddress` message.
Changing the withdraw address is possible only if the parameter `WithdrawAddrEnabled` is set to `true`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/distribution/v1beta1/tx.proto#L29-L37
The withdraw address cannot be any of the module accounts. These accounts are blocked from being withdraw addresses by being added to the distribution keeper's `blockedAddrs` array at initialization.
Response:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L29-L37
```go
func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error
if k.blockedAddrs[withdrawAddr.String()] {
fail with "`{withdrawAddr}` is not allowed to receive external funds"
@ -27,163 +30,93 @@ func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, w
## MsgWithdrawDelegatorReward
under special circumstances a delegator may wish to withdraw rewards from only
a single validator.
A delegator can withdraw its rewards.
Internally in the distribution module, this transaction simultaneously removes the previous delegation with associated rewards, the same as if the delegator simply started a new delegation of the same value.
The rewards are sent immediately from the distribution `ModuleAccount` to the withdraw address.
Any remainder (truncated decimals) are sent to the community pool.
The starting height of the delegation is set to the current validator period, and the reference count for the previous period is decremented.
The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/distribution/v1beta1/tx.proto#L42-L50
In the F1 distribution, the total rewards are calculated per validator period, and a delegator receives a piece of those rewards in proportion to their stake in the validator.
In basic F1, the total rewards that all the delegators are entitled to between to periods is calculated the following way.
Let `R(X)` be the total accumulated rewards up to period `X` divided by the tokens staked at that time. The delegator allocation is `R(X) * delegator_stake`.
Then the rewards for all the delegators for staking between periods `A` and `B` are `(R(B) - R(A)) * total stake`.
However, these calculated rewards don't account for slashing.
Taking the slashes into account requires iteration.
Let `F(X)` be the fraction a validator is to be slashed for a slashing event that happened at period `X`.
If the validator was slashed at periods `P1, ..., PN`, where `A < P1`, `PN < B`, the distribution module calculates the individual delegator's rewards, `T(A, B)`, as follows:
```
stake := initial stake
rewards := 0
previous := A
for P in P1, ..., PN`:
rewards = (R(P) - previous) * stake
stake = stake * F(P)
previous = P
rewards = rewards + (R(B) - R(PN)) * stake
```
The historical rewards are calculated retroactively by playing back all the slashes and then attenuating the delegator's stake at each step.
The final calculated stake is equivalent to the actual staked coins in the delegation with a margin of error due to rounding errors.
Response:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L42-L50
## WithdrawValidatorCommission
The validator can send the WithdrawValidatorCommission message to withdraw their accumulated commission.
The commission is calculated in every block during `BeginBlock`, so no iteration is required to withdraw.
The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator.
Only integer amounts can be sent. If the accumulated awards have decimals, the amount is truncated before the withdrawal is sent, and the remainder is left to be withdrawn later.
## FundCommunityPool
This message sends coins directly from the sender to the community pool.
The transaction fails if the amount cannot be transferred from the sender to the distribution module account.
```go
func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress)
height = GetHeight()
// get all distribution scenarios
pool = staking.GetPool()
feePool = GetFeePool()
delInfo = GetDelegationDistInfo(delegatorAddr,
validatorAddr)
valInfo = GetValidatorDistInfo(validatorAddr)
validator = GetValidator(validatorAddr)
func (k Keeper) FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error {
if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, amount); err != nil {
return err
}
feePool, withdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens,
validator.Tokens, validator.DelegatorShares, validator.Commission)
feePool := k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(amount...)...)
k.SetFeePool(ctx, feePool)
SetFeePool(feePool)
SendCoins(distributionModuleAcc, withdrawAddr, withdraw.TruncateDecimal())
return nil
}
```
## Common distribution operations
### Withdraw Validator Rewards All
These operations take place during many different messages.
When a validator wishes to withdraw their rewards it must send
array of `MsgWithdrawDelegatorReward`. 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. This
transaction withdraws the validators commission fee, as well as any rewards
earning on their self-delegation.
### Initialize delegation
Each time a delegation is changed, the rewards are withdrawn and the delegation is reinitialized.
Initializing a delegation increments the validator period and keeps track of the starting period of the delegation.
```go
// initialize starting info for a new delegation
func (k Keeper) initializeDelegation(ctx sdk.Context, val sdk.ValAddress, del sdk.AccAddress) {
// period has already been incremented - we want to store the period ended by this delegation action
previousPeriod := k.GetValidatorCurrentRewards(ctx, val).Period - 1
func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress)
// increment reference count for the period we're going to track
k.incrementReferenceCount(ctx, val, previousPeriod)
height = GetHeight()
feePool = GetFeePool()
pool = GetPool()
ValInfo = GetValidatorDistInfo(delegation.ValidatorAddr)
validator = GetValidator(delegation.ValidatorAddr)
validator := k.stakingKeeper.Validator(ctx, val)
delegation := k.stakingKeeper.Delegation(ctx, del, val)
// withdraw self-delegation
withdraw = GetDelegatorRewardsAll(validator.OperatorAddr, height)
// withdrawal validator commission rewards
feePool, commission = valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens,
validator.Tokens, validator.Commission)
withdraw += commission
SetFeePool(feePool)
SendCoins(distributionModuleAcc, withdrawAddr, withdraw.TruncateDecimal())
```
## Common calculations
### Update total validator accum
The total amount of validator accum must be calculated in order to determine
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
updated each time rewards are withdrawn from the system.
```go
func (g FeePool) UpdateTotalValAccum(height int64, totalBondedTokens Dec) FeePool
blocks = height - g.TotalValAccumUpdateHeight
g.TotalValAccum += totalDelShares * blocks
g.TotalValAccumUpdateHeight = height
return g
```
### Update validator's accums
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.
``` go
func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec) ValidatorDistInfo
blocks = height - vi.TotalDelAccumUpdateHeight
vi.TotalDelAccum += totalDelShares * blocks
vi.TotalDelAccumUpdateHeight = height
return vi
```
### FeePool pool to validator pool
Every time a validator or delegator executes a withdrawal 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. It is at this point that the
commission is withdrawn
```go
func (vi ValidatorDistInfo) TakeFeePoolRewards(g FeePool, height int64, totalBonded, vdTokens, commissionRate Dec) (
vi ValidatorDistInfo, g FeePool)
g.UpdateTotalValAccum(height, totalBondedShares)
// update the validators pool
blocks = height - vi.FeePoolWithdrawalHeight
vi.FeePoolWithdrawalHeight = height
accum = blocks * vdTokens
withdrawalTokens := g.Pool * accum / g.TotalValAccum
commission := withdrawalTokens * commissionRate
g.TotalValAccum -= accumm
vi.PoolCommission += commission
vi.PoolCommissionFree += withdrawalTokens - commission
g.Pool -= withdrawalTokens
return vi, g
```
### Delegation reward withdrawal
For delegations (including validator's self-delegation) all rewards from reward
pool have already had the validator's commission taken away.
```go
func (di DelegationDistInfo) WithdrawRewards(g FeePool, vi ValidatorDistInfo,
height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (
di DelegationDistInfo, g FeePool, withdrawn DecCoins)
vi.UpdateTotalDelAccum(height, totalDelShares)
g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate)
blocks = height - di.WithdrawalHeight
di.WithdrawalHeight = height
accum = delegatorShares * blocks
withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum
vi.TotalDelAccum -= accum
vi.Pool -= withdrawalTokens
vi.TotalDelAccum -= accum
return di, g, withdrawalTokens
```
### Validator commission withdrawal
Commission is calculated each time rewards enter into the validator.
```go
func (vi ValidatorDistInfo) WithdrawCommission(g FeePool, height int64,
totalBonded, vdTokens, commissionRate Dec) (
vi ValidatorDistInfo, g FeePool, withdrawn DecCoins)
g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate)
withdrawalTokens := vi.PoolCommission
vi.PoolCommission = 0
return vi, g, withdrawalTokens
// calculate delegation stake in tokens
// we don't store directly, so multiply delegation shares * (tokens per share)
// note: necessary to truncate so we don't allow withdrawing more rewards than owed
stake := validator.TokensFromSharesTruncated(delegation.GetShares())
k.SetDelegatorStartingInfo(ctx, val, del, types.NewDelegatorStartingInfo(previousPeriod, stake, uint64(ctx.BlockHeight())))
}
```

View File

@ -3,28 +3,55 @@ order: 5
-->
# Hooks
Available hooks that can be called by and from this module.
## Create or modify delegation distribution
- triggered-by: `staking.MsgDelegate`, `staking.MsgBeginRedelegate`, `staking.MsgUndelegate`
The pool of a new delegator bond will be 0 for the height at which the bond was
added, or the withdrawal has taken place. This is achieved by setting
`DelegationDistInfo.WithdrawalHeight` to the height of the triggering transaction.
### Before
## Commission rate change
- triggered-by: `staking.MsgEditValidator`
- The delegation rewards are withdrawn to the withdraw address of the delegator.
The rewards include the current period and exclude the starting period.
- The validator period is incremented.
The validator period is incremented because the validator's power and share distribution might have changed.
- The reference count for the delegator's starting period is decremented.
If a validator changes its commission rate, all commission on fees must be
simultaneously withdrawn using the transaction `TxWithdrawValidator`.
Additionally the change and associated height must be recorded in a
`ValidatorUpdate` state record.
### After
## Change in Validator State
- triggered-by: `staking.Slash`, `staking.UpdateValidator`
The starting height of the delegation is set to the previous period.
Because of the `Before`-hook, this period is the last period for which the delegator was rewarded.
Whenever a validator is slashed or enters/leaves the validator group all of the
validator entitled reward tokens must be simultaneously withdrawn from
`Global.Pool` and added to `ValidatorDistInfo.Pool`.
## Validator created
- triggered-by: `staking.MsgCreateValidator`
When a validator is created, the following validator variables are initialized:
- Historical rewards
- Current accumulated rewards
- Accumulated commission
- Total outstanding rewards
- Period
By default, all values are set to a `0`, except period, which is set to `1`.
## Validator removed
- triggered-by: `staking.RemoveValidator`
Outstanding commission is sent to the validator's self-delegation withdrawal address.
Remaining delegator rewards get sent to the community fee pool.
Note: The validator gets removed only when it has no remaining delegations.
At that time, all outstanding delegator rewards will have been withdrawn.
Any remaining rewards are dust amounts.
## Validator is slashed
- triggered-by: `staking.Slash`
- The current validator period reference count is incremented.
The reference count is incremented because the slash event has created a reference to it.
- The validator period is incremented.
- The slash event is stored for later use.
The slash event will be referenced when calculating delegator rewards.

View File

@ -9,9 +9,9 @@ The distribution module contains the following parameters:
| Key | Type | Example |
| ------------------- | ------------ | -------------------------- |
| communitytax | string (dec) | "0.020000000000000000" [0] |
| baseproposerreward | string (dec) | "0.010000000000000000" [1] |
| bonusproposerreward | string (dec) | "0.040000000000000000" [1] |
| baseproposerreward | string (dec) | "0.010000000000000000" [0] |
| bonusproposerreward | string (dec) | "0.040000000000000000" [0] |
| withdrawaddrenabled | bool | true |
* [0] The value of `communitytax` must be positive and cannot exceed 1.00.
* [1] `baseproposerreward` and `bonusproposerreward` must be positive and their sum cannot exceed 1.00.
* [0] `communitytax`, `baseproposerreward` and `bonusproposerreward` must be
positive and their sum cannot exceed 1.00.

View File

@ -87,7 +87,7 @@ to set up a script to periodically withdraw and rebond rewards.
1. **[Concepts](01_concepts.md)**
- [Reference Counting in F1 Fee Distribution](01_concepts.md#reference-counting-in-f1-fee-distribution)
2. **[State](02_state.md)**
3. **[End Block](03_end_block.md)**
3. **[Begin Block](03_begin_block.md)**
4. **[Messages](04_messages.md)**
- [MsgSetWithdrawAddress](04_messages.md#msgsetwithdrawaddress)
- [MsgWithdrawDelegatorReward](04_messages.md#msgwithdrawdelegatorreward)

View File

@ -38,7 +38,7 @@ const (
//
// - 0x06<valAddrLen (1 Byte)><valAddr_Bytes>: ValidatorCurrentRewards
//
// - 0x07<valAddrLen (1 Byte)><valAddr_Bytes>: ValidatorCurrentRewards
// - 0x07<valAddrLen (1 Byte)><valAddr_Bytes>: ValidatorCurrentCommission
//
// - 0x08<valAddrLen (1 Byte)><valAddr_Bytes><height>: ValidatorSlashEvent
var (

View File

@ -12,7 +12,7 @@ long as it contains precommits from +2/3 of total voting power.
Proposers are incentivized to include precommits from all validators in the Tendermint `LastCommitInfo`
by receiving additional fees proportional to the difference between the voting
power included in the `LastCommitInfo` and +2/3 (see [fee distribution](https://github.com/cosmos/cosmos-sdk/blob/master/docs/spec/fee_distribution)).
power included in the `LastCommitInfo` and +2/3 (see [fee distribution](x/distribution/spec/03_begin_block.md)).
```
type LastCommitInfo struct {