Skip to content

Commit

Permalink
docs: x/distribution spec (cosmos#8928)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* spelling error

* change link

* slashing spec clarification

* Revert "slashing spec clarification"

This reverts commit b08b5a8.

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

Co-authored-by: Robert Zaremba <[email protected]>

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

Co-authored-by: Federico Kunze <[email protected]>

* update link to latest version

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

Co-authored-by: Robert Zaremba <[email protected]>

* 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 <[email protected]>

* clarifications in concepts file

* Clarify introductory paragraphs

* communitytax => community_tax

* Apply suggestions from code review

Co-authored-by: Barrie Byron <[email protected]>
Co-authored-by: Robert Zaremba <[email protected]>

* 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 <[email protected]>

* Apply suggestions from code review

Co-authored-by: Barrie Byron <[email protected]>
Co-authored-by: Ethan Buchman <[email protected]>

Co-authored-by: Jack Zampolin <[email protected]>
Co-authored-by: Marko <[email protected]>
Co-authored-by: Robert Zaremba <[email protected]>
Co-authored-by: Federico Kunze <[email protected]>
Co-authored-by: Barrie Byron <[email protected]>
Co-authored-by: Alessio Treglia <[email protected]>
Co-authored-by: Ethan Buchman <[email protected]>
  • Loading branch information
8 people authored May 3, 2021
1 parent d19791b commit a3feeed
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 205 deletions.
6 changes: 4 additions & 2 deletions x/distribution/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
15 changes: 12 additions & 3 deletions x/distribution/spec/01_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion x/distribution/spec/02_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)`

Expand Down
87 changes: 87 additions & 0 deletions x/distribution/spec/03_begin_block.md
Original file line number Diff line number Diff line change
@@ -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)
```
33 changes: 0 additions & 33 deletions x/distribution/spec/03_end_block.md

This file was deleted.

Loading

0 comments on commit a3feeed

Please sign in to comment.